▶ 书中第六章部分程序,加上自己补充的代码,包括 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. }

《算法》BEYOND 部分程序 part 3的更多相关文章

  1. 信号量和PV操作写出Bakery算法的同步程序

    面包店烹制面包及蛋糕,由n个销售员卖出.当有顾客进店购买面包或蛋糕时,应先在取号机上取号,然后等待叫号,若有销售员空闲时便叫下一号,试用信号量和PV操作写出Bakery算法的同步程序. 设计要求 1) ...

  2. GMM算法的matlab程序

    GMM算法的matlab程序 在“GMM算法的matlab程序(初步)”这篇文章中已经用matlab程序对iris数据库进行简单的实现,下面的程序最终的目的是求准确度. 作者:凯鲁嘎吉 - 博客园 h ...

  3. GMM算法的matlab程序(初步)

    GMM算法的matlab程序 在https://www.cnblogs.com/kailugaji/p/9648508.html文章中已经介绍了GMM算法,现在用matlab程序实现它. 作者:凯鲁嘎 ...

  4. KFCM算法的matlab程序(用FCM初始化聚类中心)

    KFCM算法的matlab程序(用FCM初始化聚类中心) 在“聚类——KFCM”这篇文章中已经介绍了KFCM算法,现在用matlab程序对iris数据库进行实现,用FCM初始化聚类中心,并求其准确度与 ...

  5. KFCM算法的matlab程序

    KFCM算法的matlab程序 在“聚类——KFCM”这篇文章中已经介绍了KFCM算法,现在用matlab程序对iris数据库进行简单的实现,并求其准确度. 作者:凯鲁嘎吉 - 博客园 http:// ...

  6. FCM算法的matlab程序2

    FCM算法的matlab程序2 在“FCM算法的matlab程序”这篇文章中已经用matlab程序对iris数据库进行实现,并求解准确度.下面的程序是另一种方法,是最常用的方法:先初始化聚类中心,在进 ...

  7. FCM算法的matlab程序

    FCM算法的matlab程序 在“FCM算法的matlab程序(初步)”这篇文章中已经用matlab程序对iris数据库进行简单的实现,下面的程序最终的目的是求准确度. 作者:凯鲁嘎吉 - 博客园 h ...

  8. K-means算法的matlab程序

    K-means算法的matlab程序 在“K-means算法的matlab程序(初步)”这篇文章中已经用matlab程序对iris数据库进行简单的实现,下面的程序最终的目的是求准确度. 作者:凯鲁嘎吉 ...

  9. FCM算法的matlab程序(初步)

    FCM算法的matlab程序 在https://www.cnblogs.com/kailugaji/p/9648430.html文章中已经介绍了FCM算法,现在用matlab程序实现它. 作者:凯鲁嘎 ...

  10. K-means算法的matlab程序(初步)

    K-means算法的matlab程序 在https://www.cnblogs.com/kailugaji/p/9648369.html 文章中已经介绍了K-means算法,现在用matlab程序实现 ...

随机推荐

  1. .net(C#)常见面试题

    1. 简述 private. protected. public. internal 修饰符的访问权限. 答 . private : 私有成员, 在类的内部才可以访问. protected : 保护成 ...

  2. XE5开发Android程序调用电话相关功能(短信息和电话)

    方法a.不使用Intent而是直接发短信. smsManager对应的Delphi代码应该是: uses Androidapi.JNI.JavaTypes,Androidapi.JNI.Telepho ...

  3. [2]注解(Annotation)-- 深入理解Java:注解(Annotation)自定义注解入门

    转载 http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html 深入理解Java:注解(Annotation)自定义注解入门 要深入学习 ...

  4. WPF Demo17 数据绑定

    实例一:以资源的形式实现 namespace 数据绑定1 { public class Student { public int Id { get; set; } public string Name ...

  5. [蓝桥杯]ALGO-16.算法训练_进制转换

    问题描述 我们可以用这样的方式来表示一个十进制数: 将每个阿拉伯数字乘以一个以该数字所处位置的(值减1)为指数,以10为底数的幂之和的形式.例如:123可表示为 1*102+2*101+3*100这样 ...

  6. 【springboot】之将properties配置转为bean

    将springboot里面非application.yml 或者application.properties 里面的key-value转为JavaBean /** * @Describe: DataS ...

  7. P2837晚餐队列安排

    传送 特写此篇,纪念不用dp做dp题 洛谷说这是个dp,但我不信(其实就是不会dp),因此我们考虑用另一种思路.修改后的队列每一个 数a[i]一定满足a[i]<=a[i+1],那修改后的顺序就是 ...

  8. go中的make和new的区别

    适用范围:make 只能创建内建类型(slice map channel), new 则是可以对所有类型进行内存分配 返回值: new 返回指针, make 返回引用 填充值: new 填充零值, m ...

  9. [UE4]结构体

    只有数据变量属性,没有函数和事件

  10. join、on、where、having的使用区别

    on.where.having的区别 on.where.having这三个都可以加条件的子句中,on是最先执行,where次之,having最后.on是在生成中间的临时表时起作用的,where,hav ...