? 书中第六章部分程序,加上自己补充的代码,包括 Graham 扫描生成凸包,计算最远点对
● Graham 扫描生成凸包
1 package package01; 2 3 import java.util.Arrays; 4 import edu.princeton.cs.algs4.StdIn; 5 import edu.princeton.cs.algs4.StdOut; 6 import edu.princeton.cs.algs4.Point2D; 7 import edu.princeton.cs.algs4.Stack; 8 9 public class class01 10 { 11 private Stack<Point2D> hull = new Stack<Point2D>(); 12 13 public class01(Point2D[] points) 14 { 15 if (points == null || points.length == 0) 16 throw new IllegalArgumentException("argument is null"); 17 int n = points.length; 18 Point2D[] a = new Point2D[n]; 19 for (int i = 0; i < n; i++) 20 a[i] = points[i]; 21 22 Arrays.sort(a); // Y 坐标升序排序,等值的按 X 坐标升序排序,保证 a[0] 为最下最左,a[1] 为 23 Arrays.sort(a, 1, n, a[0].polarOrder()); // 以 a[0] 为原点,幅角升序排序 24 hull.push(a[0]); // 第一个点 25 int k1; // 找到下一个相异点 26 for (k1 = 1; k1 < n; k1++) 27 { 28 if (!a[0].equals(a[k1])) 29 break; 30 } 31 if (k1 == n) 32 return; 33 int k2; // 找到下一个非共线点 34 for (k2 = k1 + 1; k2 < n; k2++) 35 { 36 if (Point2D.ccw(a[0], a[k1], a[k2]) != 0) 37 break; 38 } 39 hull.push(a[k2 - 1]); // a[k2-1] 是与 a[0],a[k1] 共线的最后一个点(也可以先压 a[k1] 然后跳过 a[k2-1]) 40 for (int i = k2; i < n; i++) 41 { 42 Point2D top = hull.pop(); 43 for (; Point2D.ccw(hull.peek(), top, a[i]) <= 0; top = hull.pop()); // 倒数第 2 点、倒数第 1 点和当前点计算三角形面积,逆时针方向为正 44 // 吐栈吐到这 3 点的面积为正为止,压入倒数第 2 点当前点 45 hull.push(top); 46 hull.push(a[i]); 47 } 48 assert isConvex(); 49 } 50 51 public Iterable<Point2D> hull() // 得到凸包的迭代器 52 { 53 Stack<Point2D> s = new Stack<Point2D>(); 54 for (Point2D p : hull) 55 s.push(p); 56 return s; 57 } 58 59 private boolean isConvex() // 检查凸性 60 { 61 int n = hull.size(); 62 if (n <= 2) return true; 63 64 Point2D[] points = new Point2D[n]; 65 int k = 0; 66 for (Point2D p : hull()) 67 points[k++] = p; 68 69 for (int i = 0; i < n; i++) 70 { 71 if (Point2D.ccw(points[i], points[(i + 1) % n], points[(i + 2) % n]) <= 0) 72 return false; 73 } 74 return true; 75 } 76 77 public static void main(String[] args) 78 { 79 int n = StdIn.readInt(); 80 Point2D[] points = new Point2D[n]; 81 for (int i = 0; i < n; i++) 82 { 83 int x = StdIn.readInt(), y = StdIn.readInt(); 84 points[i] = new Point2D(x, y); 85 } 86 class01 graham = new class01(points); 87 for (Point2D p : graham.hull()) 88 StdOut.println(p); 89 } 90 }
● 计算最远点对
1 package package01; 2 3 import edu.princeton.cs.algs4.StdIn; 4 import edu.princeton.cs.algs4.StdOut; 5 import edu.princeton.cs.algs4.Point2D; 6 import edu.princeton.cs.algs4.GrahamScan; 7 8 public class class01 9 { 10 private Point2D best1, best2; 11 private double bestDistanceSquared = Double.NEGATIVE_INFINITY; // 当前最远点对距离的平方 12 13 public class01(Point2D[] points) 14 { 15 if (points == null || points.length <= 1) 16 throw new IllegalArgumentException("constructor argument is null"); 17 18 GrahamScan graham = new GrahamScan(points); 19 20 int m = 0;// 凸包点数 21 for (Point2D p : graham.hull()) 22 m++; 23 Point2D[] hull = new Point2D[m + 1]; // 凸包顶点放入 a[1] ~ a[m] 24 m = 1; 25 for (Point2D p : graham.hull()) 26 hull[m++] = p; 27 m--; // m 等于凸包顶点数 28 29 if (m == 1) // 所有点都相同 30 return; 31 if (m == 2) // 所有点共线 32 { 33 best1 = hull[1]; 34 best2 = hull[2]; 35 bestDistanceSquared = best1.distanceSquaredTo(best2); 36 return; 37 } 38 39 int k = 2; 40 for (; Point2D.area2(hull[m], hull[1], hull[k + 1]) > Point2D.area2(hull[m], hull[1], hull[k]); k++); // a[k] 是距离直线 a[1]a[m] 最远的点 41 42 int j = k; 43 for (int i = 1; i <= k && j <= m; i++) // j 搜索后半部分,i 搜索前半部分 44 { 45 update(hull[i], hull[j]); // i 挪动一位,检查 a[i] 和 a[j] 距离是否更大 46 for (j++; (j <= m) && Point2D.area2(hull[i], hull[i + 1], hull[j]) > Point2D.area2(hull[i], hull[i + 1], hull[j - 1]); j++) 47 // j 挪动保持 a[j] 远离直线 a[i]a[i+1] 48 update(hull[i], hull[j]); 49 } 50 } 51 52 private void update(Point2D x, Point2D y) 53 { 54 double distanceSquared = x.distanceSquaredTo(y); 55 if (distanceSquared > bestDistanceSquared) 56 { 57 best1 = x; 58 best2 = y; 59 bestDistanceSquared = distanceSquared; 60 } 61 } 62 63 public Point2D either() 64 { 65 return best1; 66 } 67 68 public Point2D other() 69 { 70 return best2; 71 } 72 73 public double distance() 74 { 75 return Math.sqrt(bestDistanceSquared); 76 } 77 78 public static void main(String[] args) 79 { 80 int n = StdIn.readInt(); 81 Point2D[] points = new Point2D[n]; 82 for (int i = 0; i < n; i++) 83 { 84 int x = StdIn.readInt(), y = StdIn.readInt(); 85 points[i] = new Point2D(x, y); 86 } 87 class01 farthest = new class01(points); 88 StdOut.println(farthest.distance() + " from " + farthest.either() + " to " + farthest.other()); 89 } 90 }
原文地址:https://www.cnblogs.com/cuancuancuanhao/p/10115990.html
时间: 2024-11-13 03:59:50