分治算法:
第一步:以x坐标的升序对点对进行排序。对于x坐标一样的点,按它的y坐标排序。这样就能得到一个排好序的点构成的线性表S.
第二步:使用排好序的线性表的中点将S分为两个大小相等的子集S1和S2。递归地找到S1和S2中的最近点对。设d1和d2分别表示两个子集中最近点对的距离。
第三步:找到S1中的点和S2中的点之间距离最近的点对,它们之间的距离用d3表示。最近的点对是距离为min(d1,d2,d3)的点对。
import java.util.*;
import java.awt.Point;;
public class FindNearestPoints2 {
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
java.io.File file = new java.io.File("scores.txt");
Scanner input = new Scanner(file);
List<Point> list = new ArrayList<Point>();
System.out.print("Show the points: ");
while(input.hasNext())
{
Point point = new Point(input.nextInt(), input.nextInt());
list.add(point);
}
System.out.println(list);
sortByX(list);
System.out.println(list);
System.out.println("The Nearest distance:");
System.out.println(findNearestPoint(list, 0, list.size() - 1));
input.close();
}
public static double findNearestPoint(List<Point> list, int beg, int end)
{
int mid = (beg + end) / 2;
List<Point> stripL = new ArrayList<Point>();
List<Point> stripR = new ArrayList<Point>();
if( end - beg + 1 < 2)
return 1000;
double d1 = findNearestPoint(list, beg, mid);
double d2 = findNearestPoint(list, mid + 1, end);
double d = min2Num(d1, d2);
for(int i = beg; i <= end; i++)
{
if(i <= mid && list.get(mid).x - list.get(i).x <= d)
stripL.add(list.get(i));
else if(i > mid && list.get(i).x - list.get(mid).x <= d)
stripR.add(list.get(i));
}
return find(stripL, stripR, d);
}
public static double find(List<Point> stripL, List<Point> stripR, double d)
{
int r = 0;
for(int i = 0; i < stripL.size(); i++)
{
while(r < stripR.size() && stripR.get(r).y <= stripL.get(i).y - d)
r++;
int r1 = r;
while(r1 < stripR.size() && Math.abs(stripR.get(r1).y - stripL.get(i).y) <= d)
{
if(distance(stripL.get(i), stripR.get(r1)) < d)
d = distance(stripL.get(i), stripR.get(r1));
r1 = r1 + 1;
}
}
return d;
}
public static void sortByX(List<Point> list)
{
int leg = list.size();
//插入排序
for(int i = 1; i < leg; i++)
{
Point point = list.get(i);
int k = i;
for(; k > 0; k--)
{
if(list.get(k - 1).x > point.x)//此处的point.x千万不能用list.get(i).x代替
//因为list中i位置的值已经改变
list.set(k, list.get(k-1));
else if(list.get(k - 1).x == point.x && list.get(k - 1).y > point.y)
list.set(k, list.get(k-1));
else
break;
}
list.set(k, point);//此处的point也不能用list.get(i)代替
}
}
public static double min3Num(double d1, double d2, double d3)
{
return ((d1 > d2)? d2:d1) > d3? d3:((d1 > d2)? d2:d1);
}
public static double min2Num(double d1, double d2)
{
return (d1 > d2)? d2:d1;
}
public static double distance(Point p, Point q)
{
return Math.sqrt((p.x - q.x) * (p.x - q.x) + (p.y - q.y) * (p.y - q.y));
}
}