平面上点对的最小距离算法-java实现

平面点对问题
输入:集合S中有n个点,n>1,
输出:所有的点对之间的最小距离.
通常算法:C(n,2)个点对计算距离,比较最小,需
O(n2)时间
分治策略:取S 的子集P,将P中的点划分成两个子
集PL和PR

MinDistance(P,X,Y)
输入:n个点的点集P,X是横坐标的排序数组,Y是纵坐标的
排序数组
输出:最近的两个点及距离。
1. 如果P中点数小于等于3,则直接计算其中的最小距离;
2. 排序X,Y;
3.做垂直线l将P划分为PL和PR,PL的点在l左边,PR的点
在l右边
4.MinDidtance(PL,XL,YL); δL = PL中的最小距离;
5.MinDistance(PR,XR,YR); δR = PR中的最小距离;
6.δ = min (δL,δR );
7.对于在垂直线两边距离δ范围内的每个点,检查是否有
点与它的距离小于δ,如果存在则将δ修改为新值.每个点至多比较6个点,n个点需要O(n)时间

分析:步1 O(1)
步2 O(nlogn)
步3 O(1)
步4-5 2T(n/2)
步6 O(1)
步7 O(n)
( ) (1) 3
) ( log )
2
( ) 2 (
= ≤
= +
T n O n
T n T n O n n
由递归树估计T(n) = O(nlog2n)

预排序的处理方法
在每次调用时将已经排好的数组分成两个排
序的子集,每次调用这个过程的时间为O(n)
( ) (1) 3
( ) 2 ( ) ( )
( ) ( ) ( log )
2
= ≤
= +
= +
T n O n
T n T O n
W n T n O n n
n
解得
T(n)=O(nlogn)
W(n) = O(nlogn)

算法的java实现代码

import java.io.IOException;
import java.math.*;

class Point{ 
    int x; 
    int y; 
};

public class NearestPoint {

 static double INF = 1e20;
 
 static double dist(Point a, Point b){ 
 return Math.sqrt((float)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); 
 
 }
 static double nearest(Point[] points, int l, int r){
  
       int n = r - l;
       if(n==2)
       {
        double d1 = dist(points[l], points[l+1]);
        double d2 = dist(points[l+1], points[r]);
        double d3 = dist(points[l], points[r]);
        if(d1 <= d2 && d1 <= d3)
        {
         return d1;
        }
        
        else if(d2 <= d3)
        {
         return d2;
        }
        else
        {
         return d3;
        }
       
       }
    if(n==1)
    {
     double b = dist(points[l], points[r]); 
     return   b;
    }
       if(n==0)
       {
        return   INF;
       }
      
       int m=points[n/2+l].x;
       double left=nearest(points, l,  l+n/2); 
       double right=nearest(points, l+n/2,  r); 
       double temp_nearest=left<right?left:right; 
      
       double ret=temp_nearest;
       for(int i=n/2-1+l; i>=0 && points[i].x>m-temp_nearest; i--)
       { 
           for(int j=n/2+l; j<=r && points[j].x<m+temp_nearest;j++)
           { 
            double   t=dist(points[i], points[j]);
               if(t<ret)
               { 
                   ret=t;
                  
               } 
           } 
       }
       return   ret; 
   }
   static void cmp(Point[] P, int n){
   
    Point temp = new Point();
    for(int i = 0; i < n; i++)
     for(int j=i; j< n; j++)
     {
      if(P[i].x > P[j].x)
      {
       temp = P[i];
       P[i] = P[j];
       P[j] = temp;
      }
     }
   }
 /**
  * @param args
  */
 public static void main(String[] args) {
  // TODO Auto-generated method stub

  int num = 0;
  
  try {
   num = System.in.read()-48;
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  
  Point[] P = new Point[num];
  
  for(int i = 0; i < num; i++)
  {
   P[i] = new Point();
   P[i].x = (int)(Math.random()*25);
   P[i].y = (int)(Math.random()*25);
  }
  
  System.out.println("随机生成的点的坐标如下:");
  for(int i = 0; i< num; i++)
  {
   System.out.println("("+P[i].x+","+P[i].y+")");
  }
  
  double min = INF;
       Point minP1 = new Point();
       Point minP2 = new Point();
      
  for(int i = 0; i < num; i++)
   for(int j = i+1; j < num; j++)
   {
    double d = dist(P[i], P[j]);
    if(d < min)
    {
     min = d;
     minP1 = P[i];
                 minP2 = P[j];
    }
   }
  System.out.println("用蛮力算法得到的最近距离为:"+min);
  System.out.println("最近点坐标为:("+minP1.x+","+minP1.y+")和("+minP2.x+","+minP2.y+")");
  
  cmp(P, num);
  
  System.out.println("按照横坐标排序后,各点坐标如下:");
  for(int i = 0; i< num; i++)
  {
   System.out.println("("+P[i].x+","+P[i].y+")");
  }
  
  min = nearest(P, 0, num-1);
  System.out.println("用分治算法得到的最近距离为:"+min);
 }
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值