【问题描述】

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. Gradle 从svn 中检出的父项目后处理配置【我】

    前提: 一个用gradle配置的 类似maven的聚合项目的项目,然后它在svn上就是一个父工程的目录. 检出方式: 在eclipse中,直接用svn资源库检出 父项目 的目录. 然后,在父项目下面的 ...

  2. ffmpeg在asp.net 视频转换

    ffmpeg是一个源于Linux的工具软件,是FLV视频转换器,可以轻易地实现FLV向其它格式avi.asf. mpeg的转换或者将其它格式转换为flv.在视频播客中,我们通常使用它把我们上传的视频转 ...

  3. IP基本原理

    IP基本原理 一.IP基本原理 IP是网络层协议,也是当今应用最广泛的网络协议之一 IP协议规定了数据的封装方式,网络节点的标识方法,用于网络上数据的端到端的传递. 1.IP及其相关协议 2.IP的主 ...

  4. Keepalive+nginx实现高可用负载均衡方案

    Keepalive+nginx实现高可用负载均衡方案 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.nginx做高可用工作在第几层? 上个月我发表了一篇keepalive+lv ...

  5. xgboost应用

    在业务中,我们经常需要对数据建模并预测.简单的情况下,我们采用 if else 判断(一棵树)即可.但如果预测结果与众多因素有关,而每一个特征的权重又不尽相同. 所以我们如何把这些特征的权重合理的找出 ...

  6. centos7环境下在线安装mysql

    卸载mariadb centos默认安装了mariadb,因此,在安装mysql之前,需要卸载系统中安装的mariadb. 查看系统中所有已安装的mariadb包.命令:rpm -qa | grep ...

  7. JAVA中初始化ArrayList的三种方式

    下面讲一下ArrayList初始化的几种不同方式. 一.最常用的初始化方式. List<String> list1 = new ArrayList<String>(); lis ...

  8. Spring面向切面编程AOP(around)实战

    spring aop的环绕通知around功能强大,我们这里就不细说,直接上代码,看着注释就能明白 需要的可以点击下载源码 1.如果使用注解的方式则需要先创建个注解类 package com.mb.a ...

  9. Simple Sort

    题目描述 You are given an unsorted array of integer numbers. Your task is to sort this array and kill po ...

  10. 20155204 2016-2017-2 《Java程序设计》第6周学习总结

    20155204 2016-2017-2 <Java程序设计>第6周学习总结 教材学习内容总结 一切皆对象,输入输出也是类,线程也是 String对象的trim方法去掉首尾空格和空字符 f ...