【问题描述】

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 寻找最邻近的点对的更多相关文章

  1. 机器学习 第4篇:sklearn 最邻近算法概述

    sklearn.neighbors 提供了针对无监督和受监督的基于邻居的学习方法的功能.监督的基于最邻近的机器学习算法是值:对带标签的数据的分类和对连续数据的预测(回归). 无监督的最近算法是许多其他 ...

  2. 机器学习 第5篇:knn回归

    基于最邻近算法的分类,本质上是对离散的数据标签进行预测,实际上,最邻近算法也可以用于对连续的数据标签进行预测,这种方法叫做基于最邻近数据的回归,预测的值(即数据的标签)是连续值,通过计算数据点最临近数 ...

  3. [Elasticsearch] 邻近匹配 (三) - 性能,关联单词查询以及Shingles

    提高性能 短语和邻近度查询比简单的match查询在性能上更昂贵.match查询仅仅是查看词条是否存在于倒排索引(Inverted Index)中,而match_phrase查询则须要计算和比較多个可能 ...

  4. [Elasticsearch] 邻近匹配 (一) - 短语匹配以及slop參数

    本文翻译自Elasticsearch官方指南的Proximity Matching一章. 邻近匹配(Proximity Matching) 使用了TF/IDF的标准全文搜索将文档,或者至少文档中的每一 ...

  5. [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 ...

  6. [LeetCode] Find Minimum in Rotated Sorted Array II 寻找旋转有序数组的最小值之二

    Follow up for "Find Minimum in Rotated Sorted Array":What if duplicates are allowed? Would ...

  7. [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 ...

  8. C语言 · 寻找数组中的最大值

    问题描述 对于给定整数数组a[],寻找其中最大值,并返回下标. 输入格式 整数数组a[],数组元素个数小于1等于100.输出数据分作两行:第一行只有一个数,表示数组元素个数:第二行为数组的各个元素. ...

  9. 【跟着子迟品 underscore】如何优雅地写一个『在数组中寻找指定元素』的方法

    Why underscore (觉得这部分眼熟的可以直接跳到下一段了...) 最近开始看 underscore.js 源码,并将 underscore.js 源码解读 放在了我的 2016 计划中. ...

随机推荐

  1. git 子模块

    为了方便各个子模块独立开发,或使用第三方不断更新的仓库,可以使用子模块来引用. 子模块对应的源码是子模块仓库的克隆. git submodule 与 subtree对比 git submodule 允 ...

  2. wagger的展示路径修改

    转:https://www.jianshu.com/p/ce7e247515f5?utm_source=oschina-app 注:本文是基于springboot配置实现,但在实际中使用springm ...

  3. read from /dev/urandom 返回值异常

    #include<stdio.h> #include<iostream> #include <fcntl.h> #include <sys/mman.h> ...

  4. memcache、redis原理对比

    一.问题:     数据库表数据量极大(千万条),要求让服务器更加快速地响应用户的需求.   二.解决方案:      1.通过高速服务器Cache缓存数据库数据      2.内存数据库     ( ...

  5. python---redis的python使用

    set以及相关: r.set("foo","bar") print(r.get("foo"))#b'bar' #在Redis中设置值,默认, ...

  6. 《高性能Mysql》讲聚簇索引

    <高性能Mysql>原文 聚簇索引如下图为聚簇所有的存储方式,聚簇实际不是一种索引,而是一种数据的存储方式,InnoDB的聚簇事假在同一个结构中保存了B-Tree索引和数据行. 当表有聚簇 ...

  7. 【1】【JUC】JDK1.8源码分析之ReentrantLock

    概要: ReentrantLock类内部总共存在Sync.NonfairSync.FairSync三个类,NonfairSync与FairSync类继承自Sync类,Sync类继承自AbstractQ ...

  8. 通过COM组件方式实现java调用C#写的DLL文件 转

    最近一段时间单位在做一个Web项目,工程师用JAVA语言,需要公用人员信息,统一用户名和密码,原有的平台中是用C#语言开发的,在网上查找解决方法,通过JAVA调用C#的DLL文件实现.网上资料很多,自 ...

  9. Linux cache 缓存过大

    linux cache 缓存过大 : 除重启服务 之外:直接释放内存方式之一: 修改配置释放cached内存: echo > /proc/sys/vm/drop_caches

  10. luogu P1593 因子和

    不要吐槽博主总做这些数论氵题 首先我们看到这种因数问题,果断质因数分解 所以当前数\(a=p_1^{k_1}*p_2^{k_2}...*p_m^{k_m}\) 可得\(a^b=p_1^{k_1*b}* ...