分治法求解最近点对问题

1:用一条竖直的线L将所有的点分成两等份  
2:递归算出左半部分的最近两点距离d1,右半部分的最近两点距离d2,取d=min(d1,d2)   
3:算出“一个在左半部分,另一个在右半部分”这样的点对的最短距离d3。
  3.1 删除所有到L的距离大于d的点。 O(n)  
  3.2 把右半平面的点按照纵坐标y排序。 O(nlogn)  
  3.3 对于左半平面内的每个点P1,找出右半平面内纵坐标与P1的纵坐标的差在d以内的点P2,计算距离取最小值,算出d3。

4:结果=min(d1,d2,d3) 


Point类:

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;


import javax.naming.InitialContext;


/**
 * @author LKJ
 * @date 2017-12-4
 * @description Point类
 */
public class Point {

double x;
double y;

/**
* @param Points:给出的测试点集
* @return 返回测试点集中点对的最近距离
*/
public static void main(String[] args) {
ArrayList<Point> Points = new ArrayList<Point>();
Points.add(new Point(2, 3));
Points.add(new Point(-2, -3));
Points.add(new Point(2.5, 3.1));
Points.add(new Point(4, -13));
Points.add(new Point(1.2, 0.3));
Points.add(new Point(-6, 1.1));
Points.add(new Point(-0.3, 0.3));
Points.add(new Point(2.8, 13));

Collections.sort(Points, new CompareXPoint()); //将点集按横坐标从小到大排序
System.out.println(new ShortestDistance().findShortestDistance(Points));
}


public Point(double x, double y) {
this.x = x;
this.y = y;
}
}


ShortestDistance类:

import java.util.ArrayList;
import java.util.Collections;


/**
 * @author LKJ
 * @date 2017-12-4
 * @description ShortestDistance类,计算点集中的点对的最近距离
 */
public class ShortestDistance {


/**
* @param givePoints:给出的点集
* @return 返回点对的最近距离
*/
public double findShortestDistance(ArrayList<Point> givePoints) {

double dist;

if(givePoints.size() < 2) dist = 0; //一个点或没有点,距离为0
else if(givePoints.size() == 2) 
//两个点,距离为这两个点之间的距离
dist = getDistance(givePoints.get(0), givePoints.get(1)); 
else {//两个以上的点

//将点集分为左右两部分
int mid = givePoints.size() / 2;
ArrayList<Point> leftPoints = new ArrayList<Point>();
ArrayList<Point> rightPoints = new ArrayList<Point>();

for(int i = 0; i < mid; i++) {
leftPoints.add(givePoints.get(i));
}
for (int i = mid; i < givePoints.size(); i++) {
rightPoints.add(givePoints.get(i));
}

//递归划分计算最近距离
dist = min(findShortestDistance(leftPoints), findShortestDistance(rightPoints));

//sLeftPoints、sRightPoints分别用来记录左右两部分距离最中间的点不超过dist的点集
ArrayList<Point> sLeftPoints = new ArrayList<Point>();
ArrayList<Point> sRightPoints = new ArrayList<Point>();

for (Point lpoint : leftPoints) {
if(Math.abs(lpoint.x - givePoints.get(mid).x) < dist) 
sLeftPoints.add(lpoint);
}
for (Point rpoint : rightPoints) {
if (Math.abs(rpoint.x - givePoints.get(mid).x) < dist) 
sRightPoints.add(rpoint);
}

//按纵坐标从小到大排序
Collections.sort(sLeftPoints, new CompareYPoint());
Collections.sort(sRightPoints, new CompareYPoint());

//计算左右两部分的最近点对距离
for (Point slpoint : sLeftPoints) {
int j = 0;
while (j < sRightPoints.size()) {
if (getDistance(slpoint, sRightPoints.get(j)) < dist) {
dist = getDistance(slpoint, sRightPoints.get(j));
}
j++;
}
}
}

return dist;

}


private double min(double a, double b) {
return a < b ? a : b;
}


/**
* @param point1、point2:任意两个点
* @return 返回两点间距离
*/
private double getDistance(Point point1, Point point2) {
double absX = Math.abs(point1.x - point2.x);
double absY = Math.abs(point1.y - point2.y);
return Math.sqrt(Math.pow(absX, 2) + Math.pow(absY, 2));
}


}


CompareXPoint类:

import java.util.Comparator;


/**
 * @author LKJ
 * @date 2017-12-4
 * @description CompareXPoint类实现Comparator对比器,按x的升序排序
 */
public class CompareXPoint implements Comparator<Point> {


@Override
public int compare(Point o1, Point o2) {
return o1.x > o2.x ? 1 : (o1.x == o2.x ? 0 : -1);
}


}


CompareXPoint类:

import java.util.Comparator;


/**
 * @author LKJ
 * @date 2017-12-4
 * @description CompareXPoint类实现Comparator对比器,按y的升序排序
 */
public class CompareYPoint implements Comparator<Point> {

@Override
public int compare(Point o1, Point o2) {
return o1.y > o2.y ? 1 : (o1.y == o2.y ? 0 : -1);
}


}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值