最近点对问题

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

算法分析与设计最近对问题

最近对问题

问题描述:

在二维平面上的n 个点中,如何快速的找出最近的一对点,就是最近点对问题。 程序设计思想:

1.蛮力法求最近对问题:

基本思想:

分别计算每一对点之间的距离,然后找出距离最小的那一对,为了避免对同一对点计

算两次距离,只考虑j i <的那些点对()

j i P P ,。

复杂度分析:

对于此算法,主要就是算两个点的欧几里得距离。注意到在求欧几里得距离时,避免了求平方根操作,其原因是:如果被开方的数越小,则它的平方根也越小。所以复杂度就是求平方,求执行次数为: )()1()(2n O n n n T =-=;即时间复杂度为)(2n O 。

2.分治法求最近对问题:

基本思想:

用分治法解决最近点对问题,就是将一个问题分解两个子问题,然后递归处理子问题,然后合并。可能两个点在每个子问题中,也可能两个点分别在两个子问题中,就这两种情况。则基本过程为:找一条中垂线m (坐位S 集合x 坐标的中位数)把n 个元素分成左右两部分元素,然后分别求得两边的最短距离1d ,2d ,然后取两者中的最小者记为d ,在中线两边分别取d 的距离,记录该距离范围内点的个数,中线左边有L 个元素,右边有R 个元素,分别将两边的点按y 坐标升序排列,在左边集合中每一个点,找右边集合的点,找到与之距离小于d 的点,更新最短距离,直到循环结束,即可求出最短距离。 复杂度分析:

应用分治法求解含有n 个点的最近对问题,其时间复杂性可由递推式表示:)()2/(*2)(n f n T n T +=。

由以上分析:合并子问题的解的时间)1()(O n f =。进而可得分治法求最近对问题的时间复杂度为:)log ()(2n n O n T =。

程序代码:

#include

#include

#include

#define NUM 1000

typedef struct{

int x;

int y;

}N;

double distance(N n1,N n2);

double minDis(double d1,double d2);

double shortestDis(N *data,int length,N *n1 , N *n2); double shortestDis(N *data,int length,N *n1 , N *n2){ int pre,last,middle,median;

int i,c1num = 0,c2num = 0,j;

N* dataP;

N* dataL;

N* CP;

N* CL;

N tn1,tn2;

double dis1 ,dis2;

// 当只有两个点时,返回最短距离,和点

if(length == 2 ){

double dis1 = distance(data[0],data[1]);

*n1 = data[0];

*n2 = data[1];

return dis1;

}else if(length == 3){

// 当只有三个点时,返回最短距离,和点

double dis1 = distance(data[0],data[1]);

double dis2 = distance(data[1],data[2]);

double dis3 = distance(data[0],data[2]);

double temp;

temp = dis1 < dis2 ? dis1:dis2;

temp = temp < dis3 ? temp : dis3;

if(temp == dis1){

*n1 = data[0];*n2 = data[1];

}else if(temp == dis2){

*n1 = data[1];*n2 = data[2];

}else{

*n1 = data[0];*n2 = data[2];

}

return temp;

}

middle =length/2;

pre = middle;

last = length - pre;

median = data[middle].x; // 记录中位数

dataP = (N*)malloc(sizeof(N)*pre);

dataL = (N*)malloc(sizeof(N)*last);

CP = (N*)malloc(sizeof(N)*pre);

CL = (N*)malloc(sizeof(N)*last);

for( i = 0;i < pre ;i++)

dataP[i] = data[i];

for( i = 0; i< last;i++)

dataL[i] = data[i+pre];

dis1 = shortestDis(dataP , pre , n1 , n2);

dis2 = shortestDis(dataL , last , &tn1 , &tn2);

if(dis1 > dis2){

*n1 = tn1;

*n2 = tn2;

}

dis1 = minDis(dis1,dis2);

for( i = 0; i < pre ; i++)

if(dataP[i].x - median < dis1){

CP[c1num++] = dataP[i];

} // 将在中位数之前的区域中与中位数距离小于最短距离的点放到CP 中

for( i = 0; i < last ; i++)

if(median - dataL[i].x < dis1){

CL[c2num++] = dataL[i];

}// 将在中位数之后的区域中与中位数距离小于最短距离的点放到CL 中

for(i = 0; i< c1num;i++){

for( j =0; j < c2num ; j++){

double temp = distance(CP[i],CL[j]);

if(temp < dis1){

dis1 = temp;

*n1 = CP[i];

*n2 = CL[j];

}

}

}//依次计算中位数两旁的区域中,每一个点与另外一个区域中的距离,并且记录最短距离

return dis1;

}

double distance(N n1,N n2){

return sqrt((n1.x -n2.x)*(n1.x -n2.x) + (n1.y - n2.y)*(n1.y - n2.y));

}

double minDis(double d1,double d2){

double d = d1 < d2 ? d1 : d2;

return d;

}

// 分治法排序

void MergeSort(N q[],int num,int mode){

相关文档
最新文档