二维最接近点对问题
分治算法:
第一步:以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)); } }