算法 分治 平面最近点对
来源:互联网 发布:吴江js华腾公寓自提柜 编辑:程序博客网 时间:2024/05/16 01:57
问题
平面最近点对问题是指:在给出的同一个平面内的所有点的坐标,然后找出这些点中最近的两个点的距离.
暴力法
//1.暴力法private static double force(List<Point> list) { int size = list.size(); double distance; double min = Double.MAX_VALUE; for (int i = 0; i < size; i++) { for (int j = i + 1; j < size; j++) { distance = dis(list.get(i), list.get(j)); if (distance < min) { min = distance; } } } return min;}分治法
先按照x坐标排序(冒泡法)
//分治前先排序private static List<Point> bubbleSort(List<Point> list) { int size = list.size(); //原理就是依次浮到顶端,for循环中体现为依次把最小的浮到底端 for (int i = 0; i < size; i++) { for (int j = i + 1; j < size; j++) { Point a = list.get(i); Point b = list.get(j); if (a.x > b.x) { Collections.swap(list, i, j); } } } //我觉得肯定不可以按Y再排序依次,假如左右有两个最高点,近乎一样高 //分治:找左,找右,找小于d //找左中的 左,右,小于d;右中的 左,右小于d。。。 return list;}
拆分成左右两份
//如果大于2,3,可以再次拆分List<Point> leftList = new ArrayList<>();List<Point> rightList = new ArrayList<>();//前半部分的点给leftListfor (int i = 0; i < size / 2; i++) { leftList.add(list.get(i));}//后半部分的点给rightList,总是可能多一个for (int i = size / 2; i < size; i++) { rightList.add(list.get(i));}
递归“求出”左右最小值d
//leftList,rightList递归double d1 = conquer(leftList);double d2 = conquer(rightList);//递归出来的结果取最小值double d = Math.min(d1, d2);左右两边处理好了,中间其实也有可能的,但是处于中轴附近d距离的才有可能比d更小
中轴线x
当左右点数相等,就是左末点和右初点的中点;
当左比右少一个,直接就是中点,即右末。
//如果左右数目相等,取左末,右初中点为xif (leftList.size() == rightList.size()) { x = (list.get(size/2 - 1).x + list.get(size/2).x) / 2;}//如果右边多一个,取中点为xelse { x = leftList.get(size/2 - 1).x;}中间范围
leftX = x - d;rightX = x + d;
在中轴的左右d距离的点,就是中区域,放入新集合
List<Point> midList = new ArrayList<>();//把集合中在mid区间的点都放进mid集合for (int i = 0; i < size; i++) { if (leftX <= list.get(i).x && rightX >= list.get(i).x) { midList.add(list.get(i)); }}暴力求出中间最小值d3,因为中间需要求的点在最坏情况下都是很少的
//暴力求出mid集合最小值double d3 = force(midList);和d比较,取最小
//比较if (d3 < d) { d = d3;}
完整代码
public class Test { static List<Point> list = new ArrayList<>(); public static void main(final String[] args) throws Exception { initData(); double resultForce = force(list); System.out.println(resultForce); bubbleSort(list); double resultConquer = conquer(list); System.out.println(resultConquer); } private static void initData() { Point p1 = new Point(1, 2); Point p2 = new Point(33, 7); Point p3 = new Point(9, 6); Point p4 = new Point(1000, 2); Point p5 = new Point(-505, 41); Point p6 = new Point(13, 12); Point p7 = new Point(18, 15); Point p8 = new Point(11, 2); Point p9 = new Point(-1000, -1000); list.add(p1); list.add(p2); list.add(p3); list.add(p4); list.add(p5); list.add(p6); list.add(p7); list.add(p8); list.add(p9); } private static double dis(Point a, Point b) { return Math.sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } //1.暴力法 private static double force(List<Point> list) { int size = list.size(); double distance; double min = Double.MAX_VALUE; for (int i = 0; i < size; i++) { for (int j = i + 1; j < size; j++) { distance = dis(list.get(i), list.get(j)); if (distance < min) { min = distance; } } } return min; } //分治前先排序 private static List<Point> bubbleSort(List<Point> list) { int size = list.size(); //原理就是依次浮到顶端,for循环中体现为依次把最小的浮到底端 for (int i = 0; i < size; i++) { for (int j = i + 1; j < size; j++) { Point a = list.get(i); Point b = list.get(j); if (a.x > b.x) { Collections.swap(list, i, j); } } } //我觉得肯定不可以按Y再排序依次,假如左右有两个最高点,近乎一样高 //分治:找左,找右,找小于d //找左中的 左,右,小于d;右中的 左,右小于d return list; } //分治(传进来一个已经按x排序过的list) private static double conquer(List<Point> list) { int size = list.size(); //如果传进来一个list(不知道有没有被拆解过的,无所谓的) //3,暴力求 if (size == 3) { return force(list); } //2,直接返回距离 if (size == 2) { return dis(list.get(0), list.get(1)); } //如果大于2,3,可以再次拆分 List<Point> leftList = new ArrayList<>(); List<Point> rightList = new ArrayList<>(); //前半部分的点给leftList for (int i = 0; i < size / 2; i++) { leftList.add(list.get(i)); } //后半部分的点给rightList,总是可能多一个 for (int i = size / 2; i < size; i++) { rightList.add(list.get(i)); } //leftList,rightList递归 double d1 = conquer(leftList); double d2 = conquer(rightList); //递归出来的结果取最小值 double d = Math.min(d1, d2); //x为中点坐标,leftX,rightX划分mid区间 double x; double leftX; double rightX; //如果左右数目相等,取左末,右初中点为x if (leftList.size() == rightList.size()) { x = (list.get(size/2 - 1).x + list.get(size/2).x) / 2; } //如果右边多一个,取中点为x else { x = leftList.get(size/2 - 1).x; } leftX = x - d; rightX = x + d; List<Point> midList = new ArrayList<>(); //把集合中在mid区间的点都放进mid集合 for (int i = 0; i < size; i++) { if (leftX <= list.get(i).x && rightX >= list.get(i).x) { midList.add(list.get(i)); } } //暴力求出mid集合最小值 double d3 = force(midList); //比较 if (d3 < d) { d = d3; } return d; }}
阅读全文
0 0
- 算法 分治 平面最近点对
- 从平面上最近的点对,谈谈分治算法
- 计算几何 平面最近点对 nlogn分治算法 求平面中距离最近的两点
- 分治法:平面最近点对问题
- hdu 1007 平面最近点对 分治
- [算法实现]基于分治的二维平面最近点对算法实现
- 平面最近点对问题—分治算法的经典应用
- C语言分治(1)___平面最近点对问题
- poj 3714 Raid 分治法求平面最近点对
- hdu1007 Quoit Design 平面最近点对(分治)
- hdu1007 Quoit Design【平面最近点对+分治】
- HDU 5721 Palace(平面最近点对(分治))
- 平面最近点对 洛谷1257 分治 c++
- java实现分治法,求平面内最近点对
- 平面最近点对
- 平面最近点对
- 平面最近点对
- 平面最近点对
- 你真的了解过度绘制吗?
- 使用gdb调试的一般步骤
- 修改centos6&rhel6.5支持auto resize the root partition
- 博客园博客地址
- 【区块链】Decentraland 挖矿教学
- 算法 分治 平面最近点对
- MySQL 服务安装及命令使用
- Hadoop介绍和环境配置
- Elasticsearch学习笔记1----常用查询操作
- SDUT 3333 数据结构实验之栈与队列六:下一较大值(二)
- 博客纪念
- windows 常用thread方法
- codeblocks的安装和使用
- 关于在web.xml上定义global error跳转页面的部分问题