【问题描述】

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. Codeforces Round #514 (Div. 2) D. Nature Reserve

    http://codeforces.com/contest/1059/problem/D 最大值: 最左下方和最右下方分别有一个点 r^2 - (r-1)^2 = (10^7)^2 maxr<0 ...

  2. 中文参考文献如何导入到endnote中

    比如我想在文献中插入“2型糖尿病患者并发脑卒中的前瞻性研究”这篇参考文献,在主题里面输入文献标题,勾选我们要找的文献,点击“导出/参考文献” 导出来以后,点击屏幕右下角界面的“导出/参考文献”,下图红 ...

  3. EClipse for PHP 中文乱码问题

    UTF-8 格式的php,中文都是乱码. 如果此时在EClipse中输入中文会有 CP1252 错误( CP1252不支持xxxx ) 解决方法: windows->preferences-&g ...

  4. NPOI学习笔记

    NPOI最简单的创建一个Excel,并且在指定单元格内填写一些数据 HSSFWorkbook workbook = new HSSFWorkbook(file); ISheet sheet = wor ...

  5. Linux记录-集群时间同步解决方案

    1.各个主机安装ntpdate 2.编写shell #!/bin/sh array=("root@master" "root@slave002" "r ...

  6. 【JUC】JDK1.8源码分析之CyclicBarrier

    一.前言 有了前面分析的基础,现在,接着分析CyclicBarrier源码,CyclicBarrier类在进行多线程编程时使用很多,比如,你希望创建一组任务,它们并行执行工作,然后在进行下一个步骤之前 ...

  7. AWT和Swing的关系

    1.AWT和Swing都是java中的包. 2.AWT(Abstract Window Toolkit):抽象窗口工具包,早期编写图形界面应用程序的包,AWT是通过调用操作系统的native方法实现的 ...

  8. centos 修改文件权限

    给脚本添加可执行权限: chmod -R 777 filename.sh

  9. Solr之.net操作

    http://www.cnblogs.com/zhangweizhong/category/771055.html 插入: SolrNet.Startup.Init<Movie>(&quo ...

  10. Keil4 几例异常解决办法

    以下几个问题在Keil5上没有发现,不过因为下载的例子都是Keil4,强迫症让我用起了Keil4 错误一:main.c: Warning: C3910W: Old syntax, please use ...