二维最接近点对问题

分治算法:

第一步:以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));
	}
}

  

转载于:https://www.cnblogs.com/wanghui390/p/FindNearestPoints.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值