《算法》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程序实现 ...
随机推荐
- 页面框架加载完自动执行函数$(function(){});
页面中有一些大的资源文件,如图片,声音等,如果一个事件绑定写在这些加载资源代码的下方,那么要等资源加载完才会绑定,这样体验不够好. 于是想不等资源加载完,只要框架加载完成就绑定事件,就可以把代码放在以 ...
- QT使用SQLite
在QT的widget中用tableview显示sqlite数据库表中的内容. 用QTcreator创建一个基于Widget类的窗口,再拖一个tableview到widget中,保存. 1.在widge ...
- windows下安装mingw-w64
mingw-w64应该可以算是mingw的改进版本吧,mingw系列编译器是非常好的并且主流的c/c++编译器 mingw-w64只负责程序的编译,只提供命令行操作没有编辑代码的图像界面,代码的编写需 ...
- Django与Vue交互,实现注册的图片验证码没有加载的原因
注册功能之图片验证码: 1.实现过程: 传递uuid给后端,再发送图片验证码的请求给后端,后端存储uuid并生成图片验证码保存到redis,然后将图片验证码返回给前端. 当用户输入图片验证码的时候,前 ...
- 经典面试题目——找到第n个丑数(参考《剑指offer(第二版)》面试题49)
一.题目大意 给你一个数n,要求返回第n个丑数.其中,丑数的定义如下: 丑数是指只包含因子2.3和5的数.(数字1也是丑数,不过是个特例)引用<剑指offer>上的话来说,对于一个数M,如 ...
- elasticsearch 口水篇(8)分词 中文分词 ik插件
先来一个标准分词(standard),配置如下: curl -XPUT localhost:9200/local -d '{ "settings" : { "analys ...
- 使用jquery.mCustomScrollbar自定义滚动条(1)
参考博客:https://blog.csdn.net/cdnight/article/details/41351505 api网址:http://manos.malihu.gr/jquery-cust ...
- visual studio中新建和使用dll
本文的目的是 创建一个最小化的dll并使用它 环境:win7 + vs2012 一个VS的解决方案(sln)下面可以有多个项目(project),所以这里新建一个解决方案,然后下面创建两个项目. 新建 ...
- 通过编写PHP代码并运用“正则表达式”来实现对试题文档进行去重复、排序
通过编写PHP代码并运用“正则表达式”来实现对试题文档进行去重复.排序 <?php $subject = file_get_contents('test.txt'); $pattern = '/ ...
- Git revert及其他一些回退操作
放弃本地的代码和本地提交,希望会退到远程分支的某次提交时,使用git reset --hard fa042ce. 本地已提交,但是发现有问题,想要撤销本地的提交,使用git checkout /trs ...