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

 

  1 package org.xiu68.exp.exp3;
  2 
  3 import java.util.ArrayList;
  4 import java.util.List;
  5 import java.util.Random;
  6 
  7 public class Exp3_2 {
  8 
  9     //设p1=(x1,y1), p2=(x2,y2), … , pn=(xn,yn)
 10     //是平面上n个点构成的集合S,设计和实现找出集合S中距离最近点对的算法。
 11     public static void main(String[] args) {
 12         // TODO Auto-generated method stub
 13         for(int i=0;i<20;i++){
 14             System.out.println("***************************");
 15             List<Point> pointList=new ArrayList<>();
 16             for(int j=0;j<50;j++){
 17                 Point p=new Point(new Random().nextInt(100),new Random().nextInt(100));
 18                 pointList.add(p);
 19             }
 20             System.out.println(bruteforce(pointList));        //蛮力法
 21             System.out.println(closestPair(pointList));        //分治法
 22             
 23             System.out.println("****************************");
 24         }
 25     }
 26 
 27     
 28     
 29     //寻找最近点对
 30     public static double closestPair(List<Point> pointList){
 31         //对pointList中的点按横坐标和纵坐标进行升序排序
 32         
 33         List<Point> sortedListX=new ArrayList<>();    
 34         List<Point> sortedListY=new ArrayList<>();    
 35         
 36         //按横坐标对数组进行升序排序
 37         pointList.sort((Point a,Point b)->{
 38             if(a.getX()<b.getX())
 39                 return -1;
 40             else 
 41                 return 1;
 42         });
 43         sortedListX.addAll(pointList);
 44         
 45         //按纵坐标对数组进行升序排序
 46         pointList.sort((Point a,Point b)->{
 47             if(a.getY()<b.getY())
 48                 return -1;
 49             else 
 50                 return 1;
 51         });
 52         sortedListY.addAll(pointList);
 53         
 54 /*        for(int i=0;i<pointList.size();i++)
 55             System.out.println(sortedListX.get(i));
 56         System.out.println("*********************");
 57         for(int i=0;i<pointList.size();i++)
 58             System.out.println(sortedListY.get(i));
 59         
 60         System.out.println("*********************");
 61         System.out.println(divide(sortedListX,sortedListY));*/
 62         
 63         return divide(sortedListX,sortedListY);
 64         
 65     }
 66     
 67     /*
 68      * 原问题的分解
 69      * sortedListX:横坐标升序排序的数组
 70      * sortedListY:纵坐标升序排序的数组
 71      */
 72     public static double divide(List<Point> sortedListX,List<Point> sortedListY){
 73         if(sortedListX.size()==1)        //如果只有一个元素
 74             return Double.MAX_VALUE;
 75         else if(sortedListX.size()==2)    //如果只有两个元素
 76             return dist(sortedListX.get(0),sortedListX.get(1));
 77         
 78         else{                            //大于2个元素
 79             int mid=sortedListX.size()/2;                //在第mid个点处把点分成左右相等的两部分
 80             double L=sortedListX.get(mid).getX();    //把点分成左右相等的两部分的直线的横坐标,设这条直线为L
 81             
 82             //L左边的点的横坐标升序排序的数组
 83             List<Point> sortedListXL=sortedListX.subList(0, mid);    
 84             
 85             //L右边的点的横坐标升序排序的数组
 86             List<Point> sortedListXR=sortedListX.subList(mid, sortedListX.size());
 87             
 88             List<Point> sortedListYL=new ArrayList<>();        //L左边的点的纵坐标升序排序的数组
 89             List<Point> sortedListYR=new ArrayList<>();        //L右边的点的纵坐标升序排序的数组
 90             
 91             //求sortedListYL与sortedListYR
 92             for(int i=0;i<sortedListY.size();i++){
 93                 Point p=sortedListY.get(i);
 94                 if(sortedListY.get(i).getX()<L){
 95                     sortedListYL.add(p);
 96                 }else{
 97                     sortedListYR.add(p);
 98                 }
 99             }
100             
101             double dL=divide(sortedListXL,sortedListYL);    //L左边两个点之间的最短距离
102             double dR=divide(sortedListXR,sortedListYR);    //L右边两个点之间的最短距离
103             
104             //比较L左边最短距离、L右边最短距离以及跨越L的顶点对之间的最短距离
105             return conquer(sortedListY,L,Math.min(dL, dR));    
106         }//else
107     }
108     
109     //子问题解的合并
110     public static double conquer(List<Point> sortedListY,double L,double d){
111         //求在L-d以及L+d之间的顶点(2d-strip)
112         List<Point> inside2DList=new ArrayList<>();
113         for(int i=0;i<sortedListY.size();i++){
114             Point p=sortedListY.get(i);
115             if(p.getX()>L-d || p.getX()<L+d){
116                 inside2DList.add(p);
117             }
118         }
119         
120         //求2d-strip之间顶点对的最短距离、与L左边和右边的最短距离比较,最小者为最终结果
121         double minDistance=d;
122         for(int i=0;i<inside2DList.size()-1;i++){
123             //i只需与i之后的11个顶点比较,i与大于11个顶点之后的顶点的距离一定大于等于d
124             for(int j=i+1;j<=i+11 && j<inside2DList.size();j++){
125                 double temp=dist(inside2DList.get(i),inside2DList.get(j));
126                 if(temp<minDistance)
127                     minDistance=temp;
128             }
129         }
130         return minDistance;
131     }
132     
133     //计算两点之间的距离
134     public static double dist(Point a,Point b){
135         return Math.sqrt(Math.pow(a.getX()-b.getX(), 2)+Math.pow(a.getY()-b.getY(), 2));
136     }
137     
138     //蛮力法
139     public static double bruteforce(List<Point> pointList){
140         double minDistance=Double.MAX_VALUE;
141         //依次比较每个顶点对
142         for(int i=0;i<pointList.size();i++){
143             for(int j=i+1;j<pointList.size();j++){
144                 double temp=dist(pointList.get(i),pointList.get(j));
145                 if(temp<minDistance)
146                     minDistance=temp;
147             }
148         }
149         return minDistance;
150     }
151 }
152 
153 class Point{
154     private double x;        //横坐标
155     private double y;        //纵坐标
156     
157     public Point(int x,int y){
158         this.x=x;
159         this.y=y;
160     }
161 
162     public double getX() {
163         return x;
164     }
165 
166     public void setX(double x) {
167         this.x = x;
168     }
169 
170     public double getY() {
171         return y;
172     }
173 
174     public void setY(double y) {
175         this.y = y;
176     }
177 
178     public String toString(){
179         return x+","+y;
180     }
181 }
View Code

 

posted @ 2017-12-05 18:08  清风☆薰衣草  阅读(542)  评论(0编辑  收藏  举报