学习记录 《常用算法大全》 分治算法 距离最近得点对

学习记录 《常用算法大全》 分治算法 距离最近得点对

输入点的坐标,输出距离最小的点和距离

1。如果点的书目较小,则直接比较
2。如果数目较大,则分成两个部分A,B
3。求A,B中的最近点对
4。求A,B中各有一点的点对的距离最小者
5。在3,4中求出的三个点对中取最小的

代码:
(error:4)

ClosestPoints.cpp
//////////////////////////////////////////////////
//
//输入点的坐标,输出距离最近的点对
//
//////////////////////////////////////////////////
#include<math.h>
#include "Merge.h"
//#include "points.h"
//数据类型1:按x排序的点
class Point1{
// friend float dist(const Point1&, const Point1&);
// friend void close(Point1*, Point2*, Point2*, int, int, Point1&, Point1&, float&);
// friend bool closest(Point1*, int, Point1&, Point1&, float&);
// friend void main();

public:
int operator <= (Point1 a)const{return (x<=a.x);}

//private:
int ID;
float x,y;
};
//数据类型2:按y排序的点
class Point2{
// friend float dist(const Point2&, const Point2&);
// friend void close(Point1*, Point2*, Point2*, int, int, Point1&, Point1&, float&);
// friend bool closest(Point1*, int, Point1&, float&);
// friend void main();

public:
int operator <= (Point2 a)const{return (y<=a.y);}

//private:
int p; // 数组X中相同的索引
float x,y;
};

//计算两点距离
template<class T>
inline float dist(const T& u, const T& v){
float dx = u.x-v.x;
float dy = u.y-v.y;
return sqrt(dx*dx + dy*dy);
}
void close(Point1 X[], Point2 Y[], Point2 Z[], int l, int r, Point1& a, Point1& b, float& d){
if(r-l ==1){
a = X[l];
b = X[r];
d = dist(X[l], X[r]);
return;
}
if(r-l ==2){
float d1 = dist(X[l], X[l+1]);
float d2 = dist(X[l+1], X[r]);
float d3 = dist(X[l], X[r]);

if(d1 <=d2 && d1 <=d3){
  a = X[l];
  b = X[l+1];
  d = d1;
  return;
}
if(d2<=d3){
  a = X[l+1];
  b = X[r];
  d = d2;
  return;
}
else{
  a = X[l];
  b = X[r];
  d = d3;
}
return;
}
//多于三个点,划分为两部分
int m = (l+r)/2;
//分别在两个部分按y排序建表
int f=l, g= m+1;
for(int i=l; i<=r; i++)
if(Y.p>m)
  Z[g++]=Y;
else
  Z[f++]=Y;
//递归求解以上两部分
close(X, Z, Y, l, m, a, b, d);
float dr;
Point1 ar, br;
close(X, Y, Z, m+1, r, ar, br, dr);
if(dr<d){
a = ar;
b = br;
d = dr;
}
Merge(Z, Y, l, m, r);//恢复(重构)Y[]

//分开的两边的点的距离 与 之前的两部分中最短距离比较
int k = l;
for(i = l; i<= r; i++)
if(fabs(Y[m].x-Y.x)<d)
  Z[k++] = Y;//x距离小于d的点放入Z
for(i=l; i<k; i++){
for(int j=i+1; j<k && Z[j].y-Z.y<d; j++){//比较y距离小于d的点
  float dp = dist(Z, Z[j]);
  if(dp<d){
  d = dp;
  a = X[Z.p];
  b = X[Z[j].p];
  }
}
}
}
bool closest(Point1 X[], int n, Point1& a, Point1& b,float& d){
//在n>=2个点中寻找最近的点对
//如果少于两个点,则返回false
//否则, 在a和b中返回距离最近的两个点
if(n<2)return false;

//按x排序
MergeSort(X, n);

//创建一个按y排序的点数组
Point2 *Y = new Point2[n];
for(int i=0; i<n; i++){
Y.p = i;
Y.x = X.x;
Y.y = Y.y;
}
MergeSort(Y, n);

Point2* Z= new Point2[n];

//寻找最近点对
close(X, Y, Z, 0, n-1, a, b, d);

delete []Y;
delete []Z;
return true;
}
void main(){}

Merge.h
#ifndef MERGE_H
#define MERGE_H
/*
template<class T>
void MergeSort(T a[], int n);
template<class T>
void MergePass(T x[], T y[], int s, int n);
template<class T>
void Merge(T c[], T d[], int i, int m, int r);*/

template <class T>
void Merge(T c[], T d[], int l, int m, int r){
int i = l;
int j = m+1;
int k = l;

//只要存在i和j,则不断归并
while((i<=m)&&(j<=r))
if(c<=c[j])
  d[k++] = c[i++];
else
  d[k++] = c[j++];

//考虑余下的部分
if(i>m)
  for(int q = j; q<=r; q++)
  d[k++] = c[q];
  else
  for(int q = i; q<=m; q++)
  d[k++] = c[q];
}
template <class T>
void MergePass(T x[], T y[], int s, int n){
int i= 0;
while(i<=n-2*s){
Merge(x, y, i, i+s-1, i+2*s-1);
i= i+2*s;
}
if((i+s)<n)Merge(x, y, i, i+s-1, n-1);
else for(int j=i; j<n-1; j++){
y[j]=x;
}
}
template <class T>
void MergeSort(T a[], int n){
T *b = new T[n];
int s=1;
while(s<n){
MergePass(a, b, s, n);
s+ = s;
MergePass(b, a, s, n);
s+ = s;
}
}

#endif

 

Tags: 分治算法  

 

posted @ 2009-10-20 08:22  java程序代码  阅读(323)  评论(0编辑  收藏  举报