《算法》BEYOND 部分程序 part 3
▶ 书中第六章部分程序,加上自己补充的代码,包括 Graham 扫描生成凸包,计算最远点对
● Graham 扫描生成凸包
- package package01;
- import java.util.Arrays;
- import edu.princeton.cs.algs4.StdIn;
- import edu.princeton.cs.algs4.StdOut;
- import edu.princeton.cs.algs4.Point2D;
- import edu.princeton.cs.algs4.Stack;
- public class class01
- {
- private Stack<Point2D> hull = new Stack<Point2D>();
- public class01(Point2D[] points)
- {
- if (points == null || points.length == 0)
- throw new IllegalArgumentException("argument is null");
- int n = points.length;
- Point2D[] a = new Point2D[n];
- for (int i = 0; i < n; i++)
- a[i] = points[i];
- Arrays.sort(a); // Y 坐标升序排序,等值的按 X 坐标升序排序,保证 a[0] 为最下最左,a[1] 为
- Arrays.sort(a, 1, n, a[0].polarOrder()); // 以 a[0] 为原点,幅角升序排序
- hull.push(a[0]); // 第一个点
- int k1; // 找到下一个相异点
- for (k1 = 1; k1 < n; k1++)
- {
- if (!a[0].equals(a[k1]))
- break;
- }
- if (k1 == n)
- return;
- int k2; // 找到下一个非共线点
- for (k2 = k1 + 1; k2 < n; k2++)
- {
- if (Point2D.ccw(a[0], a[k1], a[k2]) != 0)
- break;
- }
- hull.push(a[k2 - 1]); // a[k2-1] 是与 a[0],a[k1] 共线的最后一个点(也可以先压 a[k1] 然后跳过 a[k2-1])
- for (int i = k2; i < n; i++)
- {
- Point2D top = hull.pop();
- for (; Point2D.ccw(hull.peek(), top, a[i]) <= 0; top = hull.pop()); // 倒数第 2 点、倒数第 1 点和当前点计算三角形面积,逆时针方向为正
- // 吐栈吐到这 3 点的面积为正为止,压入倒数第 2 点当前点
- hull.push(top);
- hull.push(a[i]);
- }
- assert isConvex();
- }
- public Iterable<Point2D> hull() // 得到凸包的迭代器
- {
- Stack<Point2D> s = new Stack<Point2D>();
- for (Point2D p : hull)
- s.push(p);
- return s;
- }
- private boolean isConvex() // 检查凸性
- {
- int n = hull.size();
- if (n <= 2) return true;
- Point2D[] points = new Point2D[n];
- int k = 0;
- for (Point2D p : hull())
- points[k++] = p;
- for (int i = 0; i < n; i++)
- {
- if (Point2D.ccw(points[i], points[(i + 1) % n], points[(i + 2) % n]) <= 0)
- return false;
- }
- return true;
- }
- public static void main(String[] args)
- {
- int n = StdIn.readInt();
- Point2D[] points = new Point2D[n];
- for (int i = 0; i < n; i++)
- {
- int x = StdIn.readInt(), y = StdIn.readInt();
- points[i] = new Point2D(x, y);
- }
- class01 graham = new class01(points);
- for (Point2D p : graham.hull())
- StdOut.println(p);
- }
- }
● 计算最远点对
- package package01;
- import edu.princeton.cs.algs4.StdIn;
- import edu.princeton.cs.algs4.StdOut;
- import edu.princeton.cs.algs4.Point2D;
- import edu.princeton.cs.algs4.GrahamScan;
- public class class01
- {
- private Point2D best1, best2;
- private double bestDistanceSquared = Double.NEGATIVE_INFINITY; // 当前最远点对距离的平方
- public class01(Point2D[] points)
- {
- if (points == null || points.length <= 1)
- throw new IllegalArgumentException("constructor argument is null");
- GrahamScan graham = new GrahamScan(points);
- int m = 0;// 凸包点数
- for (Point2D p : graham.hull())
- m++;
- Point2D[] hull = new Point2D[m + 1]; // 凸包顶点放入 a[1] ~ a[m]
- m = 1;
- for (Point2D p : graham.hull())
- hull[m++] = p;
- m--; // m 等于凸包顶点数
- if (m == 1) // 所有点都相同
- return;
- if (m == 2) // 所有点共线
- {
- best1 = hull[1];
- best2 = hull[2];
- bestDistanceSquared = best1.distanceSquaredTo(best2);
- return;
- }
- int k = 2;
- 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] 最远的点
- int j = k;
- for (int i = 1; i <= k && j <= m; i++) // j 搜索后半部分,i 搜索前半部分
- {
- update(hull[i], hull[j]); // i 挪动一位,检查 a[i] 和 a[j] 距离是否更大
- for (j++; (j <= m) && Point2D.area2(hull[i], hull[i + 1], hull[j]) > Point2D.area2(hull[i], hull[i + 1], hull[j - 1]); j++)
- // j 挪动保持 a[j] 远离直线 a[i]a[i+1]
- update(hull[i], hull[j]);
- }
- }
- private void update(Point2D x, Point2D y)
- {
- double distanceSquared = x.distanceSquaredTo(y);
- if (distanceSquared > bestDistanceSquared)
- {
- best1 = x;
- best2 = y;
- bestDistanceSquared = distanceSquared;
- }
- }
- public Point2D either()
- {
- return best1;
- }
- public Point2D other()
- {
- return best2;
- }
- public double distance()
- {
- return Math.sqrt(bestDistanceSquared);
- }
- public static void main(String[] args)
- {
- int n = StdIn.readInt();
- Point2D[] points = new Point2D[n];
- for (int i = 0; i < n; i++)
- {
- int x = StdIn.readInt(), y = StdIn.readInt();
- points[i] = new Point2D(x, y);
- }
- class01 farthest = new class01(points);
- StdOut.println(farthest.distance() + " from " + farthest.either() + " to " + farthest.other());
- }
- }
《算法》BEYOND 部分程序 part 3的更多相关文章
- 信号量和PV操作写出Bakery算法的同步程序
面包店烹制面包及蛋糕,由n个销售员卖出.当有顾客进店购买面包或蛋糕时,应先在取号机上取号,然后等待叫号,若有销售员空闲时便叫下一号,试用信号量和PV操作写出Bakery算法的同步程序. 设计要求 1) ...
- GMM算法的matlab程序
GMM算法的matlab程序 在“GMM算法的matlab程序(初步)”这篇文章中已经用matlab程序对iris数据库进行简单的实现,下面的程序最终的目的是求准确度. 作者:凯鲁嘎吉 - 博客园 h ...
- GMM算法的matlab程序(初步)
GMM算法的matlab程序 在https://www.cnblogs.com/kailugaji/p/9648508.html文章中已经介绍了GMM算法,现在用matlab程序实现它. 作者:凯鲁嘎 ...
- KFCM算法的matlab程序(用FCM初始化聚类中心)
KFCM算法的matlab程序(用FCM初始化聚类中心) 在“聚类——KFCM”这篇文章中已经介绍了KFCM算法,现在用matlab程序对iris数据库进行实现,用FCM初始化聚类中心,并求其准确度与 ...
- KFCM算法的matlab程序
KFCM算法的matlab程序 在“聚类——KFCM”这篇文章中已经介绍了KFCM算法,现在用matlab程序对iris数据库进行简单的实现,并求其准确度. 作者:凯鲁嘎吉 - 博客园 http:// ...
- FCM算法的matlab程序2
FCM算法的matlab程序2 在“FCM算法的matlab程序”这篇文章中已经用matlab程序对iris数据库进行实现,并求解准确度.下面的程序是另一种方法,是最常用的方法:先初始化聚类中心,在进 ...
- FCM算法的matlab程序
FCM算法的matlab程序 在“FCM算法的matlab程序(初步)”这篇文章中已经用matlab程序对iris数据库进行简单的实现,下面的程序最终的目的是求准确度. 作者:凯鲁嘎吉 - 博客园 h ...
- K-means算法的matlab程序
K-means算法的matlab程序 在“K-means算法的matlab程序(初步)”这篇文章中已经用matlab程序对iris数据库进行简单的实现,下面的程序最终的目的是求准确度. 作者:凯鲁嘎吉 ...
- FCM算法的matlab程序(初步)
FCM算法的matlab程序 在https://www.cnblogs.com/kailugaji/p/9648430.html文章中已经介绍了FCM算法,现在用matlab程序实现它. 作者:凯鲁嘎 ...
- K-means算法的matlab程序(初步)
K-means算法的matlab程序 在https://www.cnblogs.com/kailugaji/p/9648369.html 文章中已经介绍了K-means算法,现在用matlab程序实现 ...
随机推荐
- .net(C#)常见面试题
1. 简述 private. protected. public. internal 修饰符的访问权限. 答 . private : 私有成员, 在类的内部才可以访问. protected : 保护成 ...
- XE5开发Android程序调用电话相关功能(短信息和电话)
方法a.不使用Intent而是直接发短信. smsManager对应的Delphi代码应该是: uses Androidapi.JNI.JavaTypes,Androidapi.JNI.Telepho ...
- [2]注解(Annotation)-- 深入理解Java:注解(Annotation)自定义注解入门
转载 http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html 深入理解Java:注解(Annotation)自定义注解入门 要深入学习 ...
- WPF Demo17 数据绑定
实例一:以资源的形式实现 namespace 数据绑定1 { public class Student { public int Id { get; set; } public string Name ...
- [蓝桥杯]ALGO-16.算法训练_进制转换
问题描述 我们可以用这样的方式来表示一个十进制数: 将每个阿拉伯数字乘以一个以该数字所处位置的(值减1)为指数,以10为底数的幂之和的形式.例如:123可表示为 1*102+2*101+3*100这样 ...
- 【springboot】之将properties配置转为bean
将springboot里面非application.yml 或者application.properties 里面的key-value转为JavaBean /** * @Describe: DataS ...
- P2837晚餐队列安排
传送 特写此篇,纪念不用dp做dp题 洛谷说这是个dp,但我不信(其实就是不会dp),因此我们考虑用另一种思路.修改后的队列每一个 数a[i]一定满足a[i]<=a[i+1],那修改后的顺序就是 ...
- go中的make和new的区别
适用范围:make 只能创建内建类型(slice map channel), new 则是可以对所有类型进行内存分配 返回值: new 返回指针, make 返回引用 填充值: new 填充零值, m ...
- [UE4]结构体
只有数据变量属性,没有函数和事件
- join、on、where、having的使用区别
on.where.having的区别 on.where.having这三个都可以加条件的子句中,on是最先执行,where次之,having最后.on是在生成中间的临时表时起作用的,where,hav ...