问题描述:
最近对问题要求在包含有n个点的集合S中,找出距离最近的两个点。设 p1(x1,y1),p2(x2,y2),……,pn(xn,yn)是平面的n个点。
严格地将,最近点对可能不止一对,此例输出一对即可。
分治算法通过“分”,递归解决较小的问题;“治”从子问题的解构建原问题的解。在最近点问题中,我们通过不断将集合按照左右进行分割,找出局部最优解,然后从众多局部最优解找出最终最优解。
具体思路:
取横坐标的平均值X,将集合P分为左右两部PL,PR。最近两点可能都在左边,可能都在右边,也可能左右各一点。将这三种最近距离分别称为dl,dr,dc。
其中dl和dr可以递归的计算,注意递归的终点是集合的size等于1或者2,对这两种情况就要具体计算距离了。至于dc,我们令δ=min(dl,dr)。然后将横坐标与平均值X相距δ以內的点加入中间集合,若中间集合size达到2以上,计算出中间集合內两点的最短距离,与δ比较返回并最小值。
下面给出代码:
由于最终需要给出两点坐标,所以每次递归的返回值是包含了最近两点的数组。
import java.lang.Math;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
//一个递归代码实现
//本代码实现寻找一组点列中的最近点问题,通过把点列不断分为左中右,通过递归实现查找
public class NearestNode {
public static void main(String[] args) {
System.out.println("请输入点的个数");
Scanner in = new Scanner(System.in);
double n = in.nextDouble();
ArrayList<NearestNode> array = new ArrayList<NearestNode>();
for (int i = 0; i <n ; i++) {
System.out.println("请输入下一个点的x,y坐标");
double x = in.nextDouble();
double y = in.nextDouble();
array.add(new NearestNode(x,y));
}
ArrayList<NearestNode> twonode = dis_compare(array);
printarray(twonode);
}
//构造函数,使一个NearestNode对象具有x,y值
public NearestNode(double x, double y){
this.x = x;
this.y = y;
}
private double x;
private double y;
//递归函数,
// @param array是包含平面点的点列。
//return 返回包含两最近点的数组列表
public