Expm 3_2 寻找最邻近的点对
【问题描述】
设p1=(x1,y1), p2=(x2,y2), … , pn=(xn,yn) 是平面上n个点构成的集合S,设计和实现找出集合S中距离最近点对的算法。


每一个格子最多只能存在一个点,三行最多存在12个顶点,因此对于上图中的第(i=27)个顶点来说,最多只需要比较第27个顶点与之后的11个顶点,对于i之后或之前的11个顶点之外的顶点j,即|i-j|>=12,i与j之间的距离一定大于d,因为i和j已经相隔了至少两行。两个顶点若相隔大于等于两行或两列,则他们之间的距离一定大于等于d

package org.xiu68.exp.exp3; import java.util.ArrayList;
import java.util.List;
import java.util.Random; public class Exp3_2 { //设p1=(x1,y1), p2=(x2,y2), … , pn=(xn,yn)
//是平面上n个点构成的集合S,设计和实现找出集合S中距离最近点对的算法。
public static void main(String[] args) {
// TODO Auto-generated method stub
for(int i=0;i<20;i++){
System.out.println("***************************");
List<Point> pointList=new ArrayList<>();
for(int j=0;j<50;j++){
Point p=new Point(new Random().nextInt(100),new Random().nextInt(100));
pointList.add(p);
}
System.out.println(bruteforce(pointList)); //蛮力法
System.out.println(closestPair(pointList)); //分治法 System.out.println("****************************");
}
} //寻找最近点对
public static double closestPair(List<Point> pointList){
//对pointList中的点按横坐标和纵坐标进行升序排序 List<Point> sortedListX=new ArrayList<>();
List<Point> sortedListY=new ArrayList<>(); //按横坐标对数组进行升序排序
pointList.sort((Point a,Point b)->{
if(a.getX()<b.getX())
return -1;
else
return 1;
});
sortedListX.addAll(pointList); //按纵坐标对数组进行升序排序
pointList.sort((Point a,Point b)->{
if(a.getY()<b.getY())
return -1;
else
return 1;
});
sortedListY.addAll(pointList); /* for(int i=0;i<pointList.size();i++)
System.out.println(sortedListX.get(i));
System.out.println("*********************");
for(int i=0;i<pointList.size();i++)
System.out.println(sortedListY.get(i)); System.out.println("*********************");
System.out.println(divide(sortedListX,sortedListY));*/ return divide(sortedListX,sortedListY); } /*
* 原问题的分解
* sortedListX:横坐标升序排序的数组
* sortedListY:纵坐标升序排序的数组
*/
public static double divide(List<Point> sortedListX,List<Point> sortedListY){
if(sortedListX.size()==1) //如果只有一个元素
return Double.MAX_VALUE;
else if(sortedListX.size()==2) //如果只有两个元素
return dist(sortedListX.get(0),sortedListX.get(1)); else{ //大于2个元素
int mid=sortedListX.size()/2; //在第mid个点处把点分成左右相等的两部分
double L=sortedListX.get(mid).getX(); //把点分成左右相等的两部分的直线的横坐标,设这条直线为L //L左边的点的横坐标升序排序的数组
List<Point> sortedListXL=sortedListX.subList(0, mid); //L右边的点的横坐标升序排序的数组
List<Point> sortedListXR=sortedListX.subList(mid, sortedListX.size()); List<Point> sortedListYL=new ArrayList<>(); //L左边的点的纵坐标升序排序的数组
List<Point> sortedListYR=new ArrayList<>(); //L右边的点的纵坐标升序排序的数组 //求sortedListYL与sortedListYR
for(int i=0;i<sortedListY.size();i++){
Point p=sortedListY.get(i);
if(sortedListY.get(i).getX()<L){
sortedListYL.add(p);
}else{
sortedListYR.add(p);
}
} double dL=divide(sortedListXL,sortedListYL); //L左边两个点之间的最短距离
double dR=divide(sortedListXR,sortedListYR); //L右边两个点之间的最短距离 //比较L左边最短距离、L右边最短距离以及跨越L的顶点对之间的最短距离
return conquer(sortedListY,L,Math.min(dL, dR));
}//else
} //子问题解的合并
public static double conquer(List<Point> sortedListY,double L,double d){
//求在L-d以及L+d之间的顶点(2d-strip)
List<Point> inside2DList=new ArrayList<>();
for(int i=0;i<sortedListY.size();i++){
Point p=sortedListY.get(i);
if(p.getX()>L-d || p.getX()<L+d){
inside2DList.add(p);
}
} //求2d-strip之间顶点对的最短距离、与L左边和右边的最短距离比较,最小者为最终结果
double minDistance=d;
for(int i=0;i<inside2DList.size()-1;i++){
//i只需与i之后的11个顶点比较,i与大于11个顶点之后的顶点的距离一定大于等于d
for(int j=i+1;j<=i+11 && j<inside2DList.size();j++){
double temp=dist(inside2DList.get(i),inside2DList.get(j));
if(temp<minDistance)
minDistance=temp;
}
}
return minDistance;
} //计算两点之间的距离
public static double dist(Point a,Point b){
return Math.sqrt(Math.pow(a.getX()-b.getX(), 2)+Math.pow(a.getY()-b.getY(), 2));
} //蛮力法
public static double bruteforce(List<Point> pointList){
double minDistance=Double.MAX_VALUE;
//依次比较每个顶点对
for(int i=0;i<pointList.size();i++){
for(int j=i+1;j<pointList.size();j++){
double temp=dist(pointList.get(i),pointList.get(j));
if(temp<minDistance)
minDistance=temp;
}
}
return minDistance;
}
} class Point{
private double x; //横坐标
private double y; //纵坐标 public Point(int x,int y){
this.x=x;
this.y=y;
} public double getX() {
return x;
} public void setX(double x) {
this.x = x;
} public double getY() {
return y;
} public void setY(double y) {
this.y = y;
} public String toString(){
return x+","+y;
}
}
Expm 3_2 寻找最邻近的点对的更多相关文章
- 机器学习 第4篇:sklearn 最邻近算法概述
sklearn.neighbors 提供了针对无监督和受监督的基于邻居的学习方法的功能.监督的基于最邻近的机器学习算法是值:对带标签的数据的分类和对连续数据的预测(回归). 无监督的最近算法是许多其他 ...
- 机器学习 第5篇:knn回归
基于最邻近算法的分类,本质上是对离散的数据标签进行预测,实际上,最邻近算法也可以用于对连续的数据标签进行预测,这种方法叫做基于最邻近数据的回归,预测的值(即数据的标签)是连续值,通过计算数据点最临近数 ...
- [Elasticsearch] 邻近匹配 (三) - 性能,关联单词查询以及Shingles
提高性能 短语和邻近度查询比简单的match查询在性能上更昂贵.match查询仅仅是查看词条是否存在于倒排索引(Inverted Index)中,而match_phrase查询则须要计算和比較多个可能 ...
- [Elasticsearch] 邻近匹配 (一) - 短语匹配以及slop參数
本文翻译自Elasticsearch官方指南的Proximity Matching一章. 邻近匹配(Proximity Matching) 使用了TF/IDF的标准全文搜索将文档,或者至少文档中的每一 ...
- [LeetCode] Find the Celebrity 寻找名人
Suppose you are at a party with n people (labeled from 0 to n - 1) and among them, there may exist o ...
- [LeetCode] Find Minimum in Rotated Sorted Array II 寻找旋转有序数组的最小值之二
Follow up for "Find Minimum in Rotated Sorted Array":What if duplicates are allowed? Would ...
- [LeetCode] Find Minimum in Rotated Sorted Array 寻找旋转有序数组的最小值
Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 migh ...
- C语言 · 寻找数组中的最大值
问题描述 对于给定整数数组a[],寻找其中最大值,并返回下标. 输入格式 整数数组a[],数组元素个数小于1等于100.输出数据分作两行:第一行只有一个数,表示数组元素个数:第二行为数组的各个元素. ...
- 【跟着子迟品 underscore】如何优雅地写一个『在数组中寻找指定元素』的方法
Why underscore (觉得这部分眼熟的可以直接跳到下一段了...) 最近开始看 underscore.js 源码,并将 underscore.js 源码解读 放在了我的 2016 计划中. ...
随机推荐
- JSP总结(一)——基础(汇总)
前言:原本呢,是打算只写个JSP的内置对象总结,但是没想到这个家伙的JSP总结非常不错,我就拿来用了. 注:后缀为汇总的基本上是整理一些网上的. 借鉴地址:http://www.cnblogs.com ...
- table默认的box-sizing在不同浏览器不同
转载自:https://blog.csdn.net/csm0912/article/details/88290672
- Spring(2)
前言:控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的Spring框架的核心. 控制反转一般分为两种类型,依 ...
- bottle框架剖析
bottle框架剖析 使用 源码分析 一.使用 大致有以下几部分 quick start request routing generate contents request Data template ...
- JQuery实现轮播图及其原理
源码: <!DOCTYPE html> <html> <head> <meta charset="utf-8" name="vi ...
- 05-迪米特法则(LOD 又名: 最少知道原则)
1. 背景 类与类之间的关系越密切,耦合度越大,当一个类发生变化时,对另一个类的影响也越大. 2. 定义 一个类应该对其它类保持最少的了解. 3. 解决方法 尽量降低类与类 ...
- .Net进阶系列(14)-异步多线程(async和await)(被替换)
1. 方法名前只有async,但是方法中Task实例前没有await关键字,该方法和普通方法没有什么区别,但是会报一个警告. #region 情况一 /// <summary> /// ...
- js 格式化时间、字符串指定长度、随机字符串
格式化字符串长度 方法 function formatWidth(str, width){ str += '' if(str.length<width) '+str, width) else r ...
- L1比L2更稀疏
1. 简单列子: 一个损失函数L与参数x的关系表示为: 则 加上L2正则化,新的损失函数L为:(蓝线) 最优点在黄点处,x的绝对值减少了,但依然非零. 如果加上L1正则化,新的损失函数L为:(粉线) ...
- 字体选择框QFontComboBox
self.combobox_2 = QFontComboBox(self) # 实例化字体列表框 combobox.currentFont() 返回字体选择框中当前的字体 self.combobo ...