算法实验四_空间最近点对算法
最接近点对问题实验报告
最接近点对问题一.实验目的:1.理解算法设计的基本步骤及各步的主要内容、基本要求;2.加深对分治设计方法基本思想的理解,并利用其解决现实生活中的问题;3.通过本次实验初步掌握将算法转化为计算机上机程序的方法。
二.实验内容:1.编写实现算法:给定n对点,在这n对点中找到距离最短的点对。
2.将输出数据存放到另一个文本文件中,包括结果和具体的运行时间。
3.对实验结果进行分析。
三.实验操作:1.最接近点对查找的思想:首先,将所有的点对按照x坐标排序,找到x坐标的中位数,将所有的点对分成三部分,横坐标小于x(S1)、等于x(S2)和大于x(S3)的点对,在求取每部分中的最短距离,利用分治法,一步步地分解为子问题,找到最短距离d。
由于距离最近的两个点可能在不同的区域中,需要进一步判断。
选择S1中的一个点,由于与它相比较的点的距离不可能超过d,故其配对范围为d*2d的矩形,将这个矩形划分为6份2/d*3/d的小矩形,其对角线的长度为5/6d,小于d,故S1中的任意一个点只需和S2中的6个点比较即可,最终确定最短的距离。
2.取中位数:为了减少算法的时间开销,需要将所有的点对进行分组,以中位数为基准,考虑到快速排序的不稳定性,本次排序使用了合并排序。
代码实现:template <class Type>void Merge(Type c[],Type d[],int l,int m,int r){int i = l,j = m + 1,k = l;while((i<=m)&&(j<=r)){if(c[i]<=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 Type>void MergeSort(Type a[],Type b[],int left,int right){if(left<right){int i = (left + right)/2;MergeSort(a,b,left,i);MergeSort(a,b,i+1,right);Merge(a,b,left,i,right);//合并到数组aCopy(a,b,left,right);//复制回数组a}}3.数据存入文件:本次对文件的输入没有存入文本文件中,只将输出数据输入到指定的文件夹中,用到了输出流文件。
最近点对问题
最近点对问题I.一维问题:一、问题描述和分析最近点对问题的提法是:给定平面上n个点,找其中的一对点,使得在n个点组成的所有点对中,该点对间的距离最小。
严格的讲,最接近点对可能多于1对,为简单起见,只找其中的1对作为问题的解。
简单的说,只要将每一点与其它n-1个点的距离算出,找出达到最小距离的2点即可。
但这样效率太低,故想到分治法来解决这个问题。
也就是说,将所给的平面上n个点的集合S 分成2个子集S1和S2,每个子集中约有n/2个点。
然后在每个子集中递归的求其最接近的点对。
这里,关键问题是如何实现分治法中的合并步骤,即由S1和S2的最接近点对,如何求得原集合S中的最接近点对。
如果组成S的最接近点对的2个点都在S1中或都在S2中,则问题很容易解决,但如果这2个点分别在S1和S2中,问题就不那么简单了。
下面的基本算法中,将对其作具体分析。
二、基本算法假设用x轴上某个点m将S划分为2个集合S1和S2,使得S1={x∈S|x<=m};S2={x ∈S|x>m}。
因此,对于所有p∈S1和q∈S2有p<q。
递归的在S1和S2上找出其最接近点对{p1,p2}和{q1,q2},并设d=min{|p1-p2|,|q1-q2|}。
由此易知,S中的最接近点对或者是{p1,p2},或者是{q1,q2},或者是某个{p3,q3},其中p3∈S1且q3∈S2。
如下图所示:S1 S2p1 p2 p3 q1 q2 q3图1 一维情形的分治法注意到,如果S的最接近点对是{p3,q3},即|p3-q3|<d,则p3和q3两者与m的距离不超过d,即|p3-m|<d,|q3-m|<d。
也就是说,p3∈(m-d,m],q3∈(m,m+d]。
由于每个长度为d的半闭区间至多包含S1中的一个点,并且m是S1和S2的分割点,因此(m-d,m]中至少包含一个S中的点。
同理,(m,m+d]中也至少包含一个S中的点。
数据结构与算法之最近点对
思路:结合分治法 首先将输入的坐标组按x轴值用快接读出的x轴中值m 将坐标数组分为两部分 分别处理两个子段 两子部分返回最小的两点长度leng1,leng2 得到暂时最小的两点长度leng,为MIN(leng1,leng2) 这是两个两点p、q在同一个子集情况
然后就是求两个点p、q不在同一个子集的情况 使用两个游标i、j从m和m+1遍历两个子段 由于两个子集也为有序的 若两点横轴距离大于leng或者讨论满足横轴距离 和纵轴距离都小于leng的达到6个,可以跳出内 层遍历循环
leng1=maxLength(a,low,m); leng2=maxLength(a,m+1,high); leng=leng1<leng2?leng1:leng2; for (i=m;i>low-1;i--) for (num=6,j=m+1;j<high+1;j++) { if (a[j][1]-a[i][1]>leng) continue; if (a[j][0]-a[i][0]>leng || num==0) break; x=a[j][0]-a[i][0]; y=a[j][1]-a[i][1]; z=sqrt(x*x+y*y); num--; if (z<leng) leng=z; }
最近点对算法
最近点对算法1. 简介最近点对算法(Closest Pair Algorithm)是一种用于找到平面上最近的两个点的算法。
该算法可以在给定一组点的情况下,找到距离最近的两个点,并计算出它们之间的距离。
最近点对问题在计算几何学、图像处理、数据挖掘等领域中具有广泛应用。
例如,在地理信息系统中,可以使用最近点对算法来查找距离最近的两个地理位置;在机器视觉中,可以使用该算法来寻找图像中距离最接近的两个特征点。
2. 算法思想最近点对算法采用分治策略,将问题划分为多个子问题,并通过递归求解子问题来得到整体解。
其基本思想可以概括为以下步骤:1.将所有点按照横坐标进行排序。
2.将排序后的点集平均划分为左右两部分,分别称为P_left和P_right。
3.分别在P_left和P_right中递归求解最近点对。
4.在左右两部分求得的最近点对中,选择距离更小的那一对作为候选解。
5.在区间[P_left[-1].x, P_right[0].x]内,查找可能的更近点对。
6.比较候选解与新找到的更近点对,选择距离更小的那一对作为最终解。
3. 算法实现3.1 数据结构在实现最近点对算法时,需要定义合适的数据结构来表示点。
常见的表示方法是使用二维数组或类对象。
以下是使用类对象来表示点的示例代码:class Point:def __init__(self, x, y):self.x = xself.y = y3.2 算法步骤3.2.1 排序首先,将所有点按照横坐标进行排序。
可以使用快速排序或归并排序等算法来实现排序功能。
def sort_points(points):# 使用快速排序按照横坐标进行排序# ...3.2.2 分治求解将排序后的点集平均划分为左右两部分,并递归求解最近点对。
def closest_pair(points):n = len(points)# 如果点集中只有两个点,则直接返回这两个点和它们之间的距离if n == 2:return points, distance(points[0], points[1])# 如果点集中只有三个点,则直接计算出最近点对if n == 3:d1 = distance(points[0], points[1])d2 = distance(points[0], points[2])d3 = distance(points[1], points[2])if d1 <= d2 and d1 <= d3:return [points[0], points[1]], d1elif d2 <= d1 and d2 <= d3:return [points[0], points[2]], d2else:return [points[1], points[2]], d3# 将点集平均划分为左右两部分mid = n // 2P_left = points[:mid]P_right = points[mid:]# 分别在左右两部分递归求解最近点对closest_pair_left = closest_pair(P_left)closest_pair_right = closest_pair(P_right)# 在左右两部分求得的最近点对中,选择距离更小的那一对作为候选解if closest_pair_left[1] < closest_pair_right[1]:min_pair, min_distance = closest_pair_leftelse:min_pair, min_distance = closest_pair_right3.2.3 查找更近点对在区间[P_left[-1].x, P_right[0].x]内,查找可能的更近点对。
最近点对问题
算法分析与设计最近对问题最近对问题问题描述:在二维平面上的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 <stdio.h>#include <stdlib.h>#include <math.h>#define NUM 1000typedef 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){int i,nump,numl;N* qPre;N* qLast;if(num == 1 )return;if(num%2&&num != 2){numl = num/2;nump = num/2;nump++;}else{numl = num/2;nump = num/2;}qPre = (N*)malloc(sizeof(N)*nump);qLast = (N*)malloc(sizeof(N)*numl);for(i = 0;i < nump;i++)qPre[i] = q[i];for(i = 0;i<numl;i++)qLast[i] = q[nump+i];MergeSort(qPre,nump,mode);MergeSort(qLast,numl,mode);Merge(qPre,qLast,q,nump,numl,mode);}void Merge(N *pre,N *last,N *total,int nump,int numl,int mode){ int i = 0,j = 0,k = 0;while( i< nump && j< numl ){if(mode == 0){if(pre[i].x > last[j].x ){total[k++] = pre[i++];}else{total[k++] = last[j++];}}else{if(pre[i].y > last[j].y ){total[k++] = pre[i++];}else{total[k++] = last[j++];}}}if(i == nump){for(i = j; i < numl; i++)total[k++] = last[i];}else{for(j = i; j < nump; j++)total[k++] = pre[j];}}void computeShortestDistance(N* data , int num ,int result[4]){FILE *fo;int i,j,l = 0;int *datax,*datay;double dis = 666666,temp;datax = (int*)malloc(sizeof(int)*1000);datay = (int*)malloc(sizeof(int)*1000);for(i =0; i<num ;i++){datax[i] = data[i].x;datay[i] = data[i].y;}for(i = 0;i<num;i++){for(j = i+1;j<num;j++)if((temp = (datax[i] - datax[j])*(datax[i] - datax[j]) + (datay[i] - datay[j])*(datay[i] - datay[j])) < dis){dis = temp;result[0] = datax[i];result[1] = datay[i];result[2] = datax[j];result[3] = datay[j];}}printf("\n蛮力法:\n");printf("shortest dis: %f",sqrt(dis));}void generateDots(int number){FILE *fo;int i,n1,n2;if(!(fo = fopen("data.txt","w"))){printf("open file fail");exit(1);}for(i = 0;i< number;i++){srand((i*i));n1 =rand()%8000;srand(time(NULL)*i*i);n2 = rand()%6000;if(i%2)fprintf(fo,"%d %d\n",n1,n2);elsefprintf(fo,"%d %d\n",n2,n1);}fclose(fo);}int main(){ FILE* fo;N* data;int i;N n1,n2;double dis;int re[4];// 生成数据generateDots(NUM);data = (N*)malloc(sizeof(N)*1000);if(!(fo = fopen("data.txt","r"))){printf("open file fail");exit(1);}for(i = 0;i < NUM;i++){fscanf(fo,"%d %d",&data[i].x,&data[i].y);}fclose(fo);// 合并排序,排好序的数据放置到data 中。
最近点对算法
最近点对算法
最近点对算法是一种计算平面上最近的两个点的算法。
该算法是计算机科学中的一个基本问题,也是计算几何学的研究方向之一。
最近点对问题是指在平面上给定n个点,找出其中距离最近的两个点。
该问题的一个简单暴力解法是对每对点进行距离计算,然后选取距离最小的一对。
但该算法的时间复杂度为O(n^2),当n较大时效率较低。
因此,研究者提出了更高效的算法。
其中一种著名的解法是分治法,该算法的时间复杂度为O(nlogn)。
该算法的思路是将点集分成两个子集,然后递归地计算每个子集中的最近点对,并找出跨越两个子集的最近点对。
除分治法外,还有其他更优秀的最近点对算法,如随机增量法、基于网格的算法等。
最近点对算法在计算机科学、地理信息系统、机器人技术等领域有广泛应用。
- 1 -。
求最近点对的随机算法.doc
求最近点对的随机算法分治法求解需O(nlogn)时间,而用随机算法求解可达到O(n)时间。
对于给定的平面上的n个点(x i,y i)( i=1,2,…,n)和一个距离δ,以δ为尺寸可以构造一个(逻辑上的)网格,该网格以(min{x i},min{y j})为网格的最左下点,之后以步长δ不断向右、向上伸展为长方形网格;使得(max{x i},max{y j})也含在其中。
由于所有的点均在长方形网格中,最近点对也必在其中。
对每个尺寸为δ×δ的方格,分别向左向上、向右向上、向左向下、Γ(i=1,2,3,4)。
向右向下各扩展一格,可得4个2δ×2δ的方格iδ2定理:设已知平面上的某两点的距离为δ。
若最近点对中的一个点落在某个δ×δ方格δΓ中,Γ(i=1,2,3,4)中,则在上述的4个2δ× 2δ方格iδ2至少有一个同时含有最近点对的两个点。
推论:若已知平面上的某两点的距离为δ,且算法对长方形网格中每一个2δ×2δ方格中的所有点对,均一一计算其距离,则该算法一定可以找出最近点对。
算法:1)在点集S(|S|=n)中随机地取一个子集T,使得|T|=⎣n⎦。
(按随机取样算法的分析,n个中取m个(m≤n)时间为O(n))2)对T中的所有点对逐一计算距离,求出最近点对距离δ(T)。
(点对数为⎣n⎦(⎣n⎦-1)/2,每个点对计算时间为O(1),故总的计算时间为O(⎣n⎦2)= O(n)。
)3)以δ(T)为尺寸构造一个(逻辑上的)长方形网格,(设长方形的横向共有m格,纵向共有r格。
)4) 如果m*r ≤cn (c 可取2~10,取何值合适见后面的讨论),则开设一个m×r 的指针矩阵P 、和一个m×r 的计数矩阵Q , 然后逐一扫描S 中的点s k :如果s k 落在方格ij δΓ中(i,j 分别表示所在方格横向、纵向位置),则把该点放入P[i,j]所指的链表内,Q[i,j]增1,直至n 个点全部检查为止。
求两组点之间的最近点对实验总结
求两组点之间的最近点对实验总结在计算几何学和算法设计中,求两组点之间的最近点对是一个重要且常见的问题。
在这篇文章中,我将从简到繁地探讨这个主题,深入分析求解最近点对的算法,并进行实验总结,以便读者能更深入地理解这一概念。
一、什么是最近点对问题?最近点对问题是指在一个平面上给定n个点,要求在这些点中找到距离最近的两个点。
这个问题在实际中有着广泛的应用,比如计算机视觉中的物体识别、无人驾驶车辆的障碍物检测等都涉及到最近点对的计算。
设计高效的算法来解决最近点对问题具有重要意义。
二、最近点对的暴力解法最简单的方法是通过遍历所有点对,计算它们之间的距离,并找到最小值。
这种暴力解法的时间复杂度为O(n^2),空间复杂度为O(1),虽然简单易懂,但对于大规模的数据集来说效率较低。
三、分治法解决最近点对问题分治法是解决最近点对问题的常见方法,其基本思想是将点集分成两个子集,分别求解最近点对,然后再找出整个点集的最近点对。
在这个过程中需要用到分治、筛选和合并三个步骤。
具体算法流程如下:1. 将点集按照x坐标排序,找到中间线将点集分成左右两个子集。
2. 递归求解左右子集的最近点对。
3. 筛选出距离中线距离小于当前最近距离的点,将它们按照y坐标排序。
4. 在筛选后的点集中,以每个点为中心,向上下各取6个点。
5. 计算这些点之间的距离,更新最近距离。
6. 合并左右子集的结果,得到最终的最近点对。
使用分治法解决最近点对问题的时间复杂度为O(nlogn),效率较高,适用于大规模数据集。
四、实验总结及个人观点在进行最近点对的实验过程中,我发现分治法在处理大规模数据集时具有明显的优势,其算法设计合理、程序实现简单高效。
对于中等规模的数据集,暴力解法也能够得到较好的结果,但对于大规模数据集来说效率明显低于分治法。
我个人认为在解决最近点对问题时,应优先考虑使用分治法,并且可以根据数据规模选择不同的算法来达到更高的效率。
总结来说,求两组点之间的最近点对是一个重要且常见的问题,在实际应用中具有广泛的意义。
最近点对问题
最近点对问题I.一维问题:一、问题描述和分析最近点对问题的提法是:给定平面上n个点,找其中的一对点,使得在n个点组成的所有点对中,该点对间的距离最小。
严格的讲,最接近点对可能多于1对,为简单起见,只找其中的1对作为问题的解。
简单的说,只要将每一点与其它n-1个点的距离算出,找出达到最小距离的2点即可。
但这样效率太低,故想到分治法来解决这个问题。
也就是说,将所给的平面上n个点的集合S 分成2个子集S1和S2,每个子集中约有n/2个点。
然后在每个子集中递归的求其最接近的点对。
这里,关键问题是如何实现分治法中的合并步骤,即由S1和S2的最接近点对,如何求得原集合S中的最接近点对。
如果组成S的最接近点对的2个点都在S1中或都在S2中,则问题很容易解决,但如果这2个点分别在S1和S2中,问题就不那么简单了。
下面的基本算法中,将对其作具体分析。
二、基本算法假设用x轴上某个点m将S划分为2个集合S1和S2,使得S1={x∈S|x<=m};S2={x ∈S|x>m}。
因此,对于所有p∈S1和q∈S2有p<q。
递归的在S1和S2上找出其最接近点对{p1,p2}和{q1,q2},并设d=min{|p1-p2|,|q1-q2|}。
由此易知,S中的最接近点对或者是{p1,p2},或者是{q1,q2},或者是某个{p3,q3},其中p3∈S1且q3∈S2。
如下图所示:S1 S2p1 p2 p3 q1 q2 q3图1 一维情形的分治法注意到,如果S的最接近点对是{p3,q3},即|p3-q3|<d,则p3和q3两者与m的距离不超过d,即|p3-m|<d,|q3-m|<d。
也就是说,p3∈(m-d,m],q3∈(m,m+d]。
由于每个长度为d的半闭区间至多包含S1中的一个点,并且m是S1和S2的分割点,因此(m-d,m]中至少包含一个S中的点。
同理,(m,m+d]中也至少包含一个S中的点。
求最近点对的随机算法
求最近点对的随机算法分治法求解需O(nlogn)时间,而用随机算法求解可达到O(n)时间。
对于给定的平面上的n个点(x i,y i) (i=1,2,…,n)和一个距离δ,以δ为尺寸可以构造一个(逻辑上的)网格,该网格以(min{x i},min{y j})为网格的最左下点,之后以步长δ不断向右、向上伸展为长方形网格;使得(max{x i},max{y j})也含在其中。
由于所有的点均在长方形网格中,最近点对也必在其中。
对每个尺寸为δ×δ的方格,分别向左向上、向右向上、向左向下、向右向下各扩展一格,可得4个2δ×2δ的方格iΓ(i=1,2,3,4)。
δ2定理:设已知平面上的某两点的距离为δ。
若最近点对中的一个点落在某个δ×δ方格Γδ中,则在上述的4个2δ× 2δ方格iΓ(i=1,2,3,4)中,δ2至少有一个同时含有最近点对的两个点。
推论:若已知平面上的某两点的距离为δ,且算法对长方形网格中每一个2δ×2δ方格中的所有点对,均一一计算其距离,则该算法一定可以找出最近点对。
算法:1、点集S(|S|=n)中随机地取一个子集T,使得|T|=⎣n⎦。
(按随机取样算法的分析,n个中取m个(m≤n)时间为O(n))2、T中所有点对逐一计算距离,求出最近点对距离δ(T)。
(点对数为⎣n⎦(⎣n⎦-1)/2,每个点对计算时间为O(1),故总的计算时间为O(⎣n⎦2)= O(n)。
)3、δ(T)为尺寸构造一个(逻辑上的)长方形网格:令m=⎡(最右边点的x坐标-最左边点的x坐标)/ δ(T)⎤r=⎡(最上边点的y坐标-最下边点的y坐标)/ δ(T)⎤,则长方形的横向共有m格,纵向共有r格。
4、如果m*r≤c*n(c可取2~10,取何值合适后面讨论),则开设一个m×r的指针矩阵P、和一个m×r的计数矩阵Q,然后逐一扫描S中的点s k:如果s k落在方格ijδΓ中(i,j分别表示所在方格横向、纵向位置),则把该点放入P[i,j]所指的链表内,Q[i,j]增1,直至n个点全部检查为止。
【精品】最近点对问题
【精品】最近点对问题点对问题是计算机科学中常见的算法问题,也称为最近点对问题。
其目标是在给定一组点的集合中找到最近的两个点。
在这个问题中,我们将使用分治法来解决最近点对问题。
算法的基本思想是将点集按照x坐标进行排序,并将其分成两个子集。
然后,我们对每个子集递归地应用算法,直到子集中只有一个或两个点。
在这种情况下,我们可以直接计算出最近的点对。
然而,当子集中有超过两个点时,我们需要将问题分解成更小的子问题。
我们选择一个中间点,将点集分成两个子集,并计算出每个子集中的最近点对。
然后,我们需要考虑横跨两个子集的点对。
我们使用一个辅助函数来计算两个子集中的最近点对,并返回最小距离。
在计算最近点对时,我们需要考虑两个子问题。
首先,我们需要找到两个子集中的最近点对。
其次,我们需要找到横跨两个子集的最近点对。
为了找到两个子集中的最近点对,我们可以使用递归地应用相同的算法。
我们将两个子集分别按照y坐标进行排序,并计算出每个子集中的最近点对。
然后,我们需要考虑两个子集之间的点对。
我们将点集中的点按照y坐标进行排序,并找到一个以中间点为中心,距离中间点小于最小距离的点集。
然后,我们可以使用一个循环来比较这些点对,并计算出最小距离。
在计算横跨两个子集的最近点对时,我们需要考虑两个子集之间的点对。
我们将点集中的点按照y坐标进行排序,并找到一个以中间点为中心,距离中间点小于最小距离的点集。
然后,我们可以使用一个循环来比较这些点对,并计算出最小距离。
最后,我们将上述步骤的结果与之前计算的最小距离进行比较,选择较小的距离作为最终的最近点对。
分治法是解决最近点对问题的一个有效方法。
它通过将问题分解成更小的子问题,然后递归地解决这些子问题,最终得到整个问题的解。
在最近点对问题中,我们通过将点集按照x坐标和y坐标进行排序,并使用分治法找到最近点对。
通过使用分治法,我们可以在O(nlogn)的时间复杂度内解决最近点对问题。
这使得它成为处理大规模数据集的理想选择。
最接近点对问题算法
最接近点对问题算法
最接近点对问题是指在平面上给定N个点,找出其中距离最
近的两个点的距离。
可以使用以下算法来解决最接近点对问题:
1. 将所有点按照水平或垂直坐标排序,以便可以更方便地进行后续操作。
2. 将所有点分为两个大致相等的集合,分别称为左集合和右集合。
3. 递归地在左集合和右集合中找出最小距离的点对。
4. 取两个集合中最小距离的点对中较小的距离minDistance。
5. 在以水平坐标为准的线段中,确认是否存在两个点,它们的横坐标之差小于minDistance,并计算它们的距离。
6. 在以垂直坐标为准的线段中,确认是否存在两个点,它们的纵坐标之差小于minDistance,并计算它们的距离。
7. 取步骤5和步骤6中距离的最小值,记为delta。
8. 在左集合和右集合中,找出间距水平线的范围内的点,并按照纵坐标排序。
9. 使用二重循环,依次计算两个集合中的相邻点对之间的距离,直到纵坐标的差大于等于delta。
10. 比较得到的距离和minDistance,取较小的值作为最终的最小距离。
以上算法的时间复杂度为O(nlogn),其中n为点的数量。
中科大软院算法导论最近点对算法_C++
实验四求最近点对算法1.算法设计思路:设共有n个点,找其中距离最近的两点及其距离。
(1)蛮力法:蛮力法的思路是把所有点之间距离比较找出中间最小的。
先假设最短距离是第一个元素和第二个元素的距离,然后求第一个元素与其后的(n-1)个元素各自的距离,若比之前记录的最短距离小则记录当前值···求第i个元素与其后的(n-i)个元素各自的距离,记录之前所得到的所有距离中的最小值,直到计算到第(n-1)个元素与第n个元素的距离,此时记录的距离即为这n个元素中的最短距离。
(2)分治法:分治法是把一个大的问题划分成相似的小问题,采用递归的思想。
找中线把n个元素分成左右两部分元素分别求得两边的最短距离,然后取两者中的最小者记为l,在中线两边分别取l的距离,记录该距离范围内点的个数,中线左边有L个元素,右边有R个元素,求左边元素到右边元素的距离看其是否小于之前记录的最短距离,小则记录下来,此时的右边元素只取y值和左边元素y值距离小于l的(减少循环次数)。
循环结束即可找到最小的距离。
2.程序代码:#include<iostream>#include<cstdlib>#include<ctime>#include<cmath>using std::cout;using std::endl;#define N 5int x[N],y[N],record[N]; //产生原始点数据,x坐标放在x[]中,y坐标放在y[]中。
double Min;//////////////////////////产生随机数组/////////////////////////////void randnum(){int i;srand(time(0));for (i=0;i<N;i++){x[i]=rand()%N;cout<<x[i]<<' ';}cout<<endl;for (i=0;i<N;i++){y[i]=rand()%N;cout<<y[i]<<' ';}cout<<endl;}//////////////////////////////交换数组元素/////////////////////////// void swap(int & a, int & b){int temp=a;a=b;b=temp;}///////////////////////////////求平方///////////////////////////////////int square(int x){return x*x;}/////////////////////////////////////求两点之间距离////////////////////double lengthf(int x1,int y1,int x2,int y2){return sqrt(square(x1-x2)+square(y1-y2));}//////////////////////////////////求两者中最小者////////////////////// double min(double a,double b){if (a>=b)return b;elsereturn a;}////////////////////////////对平面数组排序//////////////////////////// void sort(int A[]){int i,j;for (i=0;i<N;i++)record[i]=i;for (j=1;j<N;j++){i=j;while (i>=0&&A[i]<A[i-1]){swap(A[i],A[i-1]);swap(record[i-1],record[i]); //得到x排序后对应的原y的坐标i--;}}cout<<"排序后的元素数组:"<<endl;for (i=0;i<N;i++)cout<<A[i]<<' ';cout<<endl;for (i=0;i<N;i++)cout<<record[i]<<' ';cout<<endl;}///////////////////////////穷举法找最小点对///////////////////////////////double exhaustion(){int i,j,k1,k2;double num;double length;num=10000;k1=k2=-1;for (j=0;j<N-1;j++){for (i=j+1;i<N;i++){length=lengthf(x[i],y[i],x[j],y[j]);if (length<num){num=length;k1=i;k2=j;}}}cout<<"平面数组最短距离是:"<<endl;cout<<"min="<<num<<endl;cout<<"对应数组下标及点坐标为:"<<endl;cout<<"i="<<k1<<','<<k2<<endl;cout<<"(x1,y1)="<<'('<<x[k1]<<','<<y[k1]<<')'<<endl<<"(x2,y2)="<<'('<<x[k2]<<','<<y[k2]<<')' <<endl;return num;}////////////////////////////////////分治法////////////////////////////////*************************************************************************/double merge(int left,int right){double mlength;if (right==left)mlength=10e-6;if (right==left+1)mlength=lengthf(x[right],y[record[right]],x[left],y[record[left]]); //两个点时求最小值if (right-left==2)mlength=min(min(lengthf(x[right-1],y[record[right-1]],x[left],y[record[left]]),lengthf(x[right],y[re cord[right]],x[left+1],y[record[left+1]])),lengthf(x[right],y[record[right]],x[left],y[record[left]]));//三个点时求最大值return mlength;}double divide(int left,int right){if (right-left<=2){Min=merge(left,right);}else{double l1,l2,mi; //l1记录划分区域后左半面最小距离,l2记录右半面最小距离,min为两者中较小者,m为全部中的最小者int rem1,rem2,l; //记录获得最短距离对应的两个点//int il,jl,ir,jr;int i,j;int R,L;R=L=0; //记录划分小区域后的左半块和右半块个有多少元素l1=l2=Min=100;l=(right-left+1)/2-1; //中线位置///////////////////////////////////////////////////l1=divide(left,l);l2=divide(l+1,right);if (l1<l2){Min=l1;//cout<<"两半面最短距离是:"<<min;else{Min=l2;//cout<<"两半面最短距离是:"<<min;}///////////////////得到右半块元素数R//cout<<"min="<<min<<endl;for (i=l+1;i<N;i++){if (x[i]-x[l]<=Min)R++;else break;}//cout<<"R="<<R<<endl;/////////////////////得到左半块元素数Lfor (i=l;i>=0;i--){if (x[l]-x[i]<=Min)L++;else break;}//cout<<"L="<<L<<endl;if (L!=0&&R!=0){for (i=l-L+1;i<=l;i++)for (j=l+1;j<=l+R;j++){if (y[record[j]]-y[record[i]]<Min||-Min<y[record[j]]-y[record[i]]){mi=lengthf(x[i],y[record[i]],x[j],y[record[j]]);if (mi<Min){Min=mi;rem1=i;rem2=j;}}}// cout<<"min="<<min<<endl;//cout<<"rem1="<<rem1<<endl<<"rem2="<<rem2<<endl;}return Min;}/***********************************************************************///////////////////////////////////主函数///////////////////////////////////int main(){//double a;randnum();cout<<"***************************遍历法*************************"<<endl;exhaustion();cout<<"***************************分治法*************************"<<endl;sort(x);divide(0,N-1);cout<<"元素组中最短距离为:"<<endl;cout<<"min="<<Min<<endl;return 0;}3.实验数据及实验结果:实验数据:随机产生的五个点坐标分别为:(1,3),(4,2),(3,0),(2,0),(0,3)实验结果:用蛮力法得到平面数组最短距离为:min=1用分治法得到平面数组最短距离为:min=14.实验总结:从本次试验中得到的领悟是:分治法事把问题分解成两个相似小问题,子问题和原来的大问题解决方法一样所以可以用递归,分治法重要是找到递归出口,什么时候递归结束,一般都有元素个数的限制。
最近点对问题
算法分析与设计最近对问题最近对问题问题描述:在二维平面上的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 <stdio.h>#include <stdlib.h>#include <math.h>#define NUM 1000typedef 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){int i,nump,numl;N* qPre;N* qLast;if(num == 1 )return;if(num%2&&num != 2){numl = num/2;nump = num/2;nump++;}else{numl = num/2;nump = num/2;}qPre = (N*)malloc(sizeof(N)*nump);qLast = (N*)malloc(sizeof(N)*numl);for(i = 0;i < nump;i++)qPre[i] = q[i];for(i = 0;i<numl;i++)qLast[i] = q[nump+i];MergeSort(qPre,nump,mode);MergeSort(qLast,numl,mode);Merge(qPre,qLast,q,nump,numl,mode);}void Merge(N *pre,N *last,N *total,int nump,int numl,int mode){ int i = 0,j = 0,k = 0;while( i< nump && j< numl ){if(mode == 0){if(pre[i].x > last[j].x ){total[k++] = pre[i++];}else{total[k++] = last[j++];}}else{if(pre[i].y > last[j].y ){total[k++] = pre[i++];}else{total[k++] = last[j++];}}}if(i == nump){for(i = j; i < numl; i++)total[k++] = last[i];}else{for(j = i; j < nump; j++)total[k++] = pre[j];}}void computeShortestDistance(N* data , int num ,int result[4]){FILE *fo;int i,j,l = 0;int *datax,*datay;double dis = 666666,temp;datax = (int*)malloc(sizeof(int)*1000);datay = (int*)malloc(sizeof(int)*1000);for(i =0; i<num ;i++){datax[i] = data[i].x;datay[i] = data[i].y;}for(i = 0;i<num;i++){for(j = i+1;j<num;j++)if((temp = (datax[i] - datax[j])*(datax[i] - datax[j]) + (datay[i] - datay[j])*(datay[i] - datay[j])) < dis){dis = temp;result[0] = datax[i];result[1] = datay[i];result[2] = datax[j];result[3] = datay[j];}}printf("\n蛮力法:\n");printf("shortest dis: %f",sqrt(dis));}void generateDots(int number){FILE *fo;int i,n1,n2;if(!(fo = fopen("data.txt","w"))){printf("open file fail");exit(1);}for(i = 0;i< number;i++){srand((i*i));n1 =rand()%8000;srand(time(NULL)*i*i);n2 = rand()%6000;if(i%2)fprintf(fo,"%d %d\n",n1,n2);elsefprintf(fo,"%d %d\n",n2,n1);}fclose(fo);}int main(){ FILE* fo;N* data;int i;N n1,n2;double dis;int re[4];// 生成数据generateDots(NUM);data = (N*)malloc(sizeof(N)*1000);if(!(fo = fopen("data.txt","r"))){printf("open file fail");exit(1);}for(i = 0;i < NUM;i++){fscanf(fo,"%d %d",&data[i].x,&data[i].y);}fclose(fo);// 合并排序,排好序的数据放置到data 中。
最近点对问题线扫描算法
最近点对问题线扫描算法
最近点对问题是一种计算几何问题,其目标是寻找在给定点集中距离最近的两个点。
线扫描算法是一种有效的解决该问题的方法,它的时间复杂度为O(n log n)。
具体的线扫描算法过程如下:
1. 排序:首先对给定的点集进行排序,以便按照一定的顺序处理点。
2. 扫描线:然后,从左到右扫描这些点,每次选择一个点作为当前扫描线的端点。
3. 计算距离:对于当前扫描线上的每个点,计算它与未被处理的点的距离。
4. 更新最近点对:如果发现更近的点对,则更新最近点对。
5. 重复步骤:重复步骤2-4,直到所有点都被处理完。
这种算法的关键在于利用线扫描来减少需要处理的点的数量,从而在O(n log n)的时间内找到最近的点对。
最接近点对问题
.
11
能否在线性时间内找到p3,q3
❖ 第一步筛选:如果最近点对由S1中的p3和 S2中的q3组成,则p3和q3一定在划分线L 的距离d内。
需要计算P1中的每个点与. P2中的每个点的距离? 12
并不必计算P1中的每个点与P2中的每个点的距离!O(n2)
❖ 第二步筛选:考虑P1中任意一点p,它若与 P2中的点q构成最接近点对的候选者,则必 有distance(p,q)<d。满足这个条件的P2 中的点一定落在一个d×2d的矩形R中
点,则此点就是S2中最小点。
因此,我们用线性时间就能找到区间(m-d,m]和(m,m+d]中所
有点,即p3和q3。从而我们用线性时间就可以将S1的解和S2的
解合并成为S的解。
.
9
❖ public static double Cpair1(S,d) //找S中最接近点对的距离d
❖{
❖ n=|S|; //S中点的个数
若矩形R中有多于6个S中的 点,则由鸽舍原理易知至少有 一个(d/2)×(2d/3)的小矩形中 有2个以上S中的点。
设u,v是位于同一小矩形中 的2个点,则
(x(u) x(v))2 ( y(u) y(v))2 (d / 2)2 (2d / 3)2 25 d 2
distance(u,v)<d。这与d的. 意义相矛盾。 36 15
distance ( u, v)
(x(u) x(v))2 ( y(u) y(v))2 (z(u) z(v))2 (d / 2)2 (d / 2)2 (2d / 3)2 17 d 2 18
distance(u,v)<d。这与d的. 意义相矛盾。
23
算法实验四_空间最近点对算法
算法实验四_空间最近点对算法⼀、算法分析该算法的问题描述为:给定⼆维平⾯上的点集,求解距离最近的两个点,并计算出两点间的距离。
解决问题最初的思路为穷举法。
对所有两点间的组合计算其距离。
然后对其进⾏⽐较,找出最⼩值即可。
不过这样做的缺点是时间复杂度和空间复杂度⼗分庞⼤,消耗巨量资源。
如有n个点的平⾯上,计算的复杂度能达到n*n。
因此设计出⼀个⾼效的算法来代替穷举法是有现实意义的。
在思考问题的过程中,可以考虑使⽤分治法的思想,以x,y中x坐标作为划分区间的标准。
将平⾯点集⼀分为⼆。
求解其中的最⼩点对。
由此产⽣的问题为划分点附近两个区间中两点的距离可能⼩于各⾃区间中的最⼩值,产⽣了纰漏。
因此在在分治的过程中,加⼊分界线附近的点对最⼩值求解函数。
分界线区域内区间的选取标准为d。
其中d为左半区间和右半区间的最⼩值中的较⼩值。
在具体实现中,⾸先建⽴⼀个空数组存放按y坐标排序的点集,判断两个相邻点之间的y坐标差值,若⼤于d,则两点间距离⼀定⼤于d,可以直接跳过,继续判断下⼀个点对。
若⼩于d,则继续计算两点间的实际距离,若⼤于d,则跳过,⼩于d,将最⼩值更新为该点对距离。
⼆、算法实现该算法的具体实现使⽤了两种求解⽅法,穷举法和分治法。
其中,穷举法⽤于判断最近点对算法实现结果的正确性。
算法使⽤的数据结构为数组,其中为了简单起见,将x轴坐标与y轴坐标分别存⼊两个数组,并新建⼀个数组record[],记录数组y的元素下标,⽤于绑定x坐标对应的y坐标。
在设计过程中使⽤到了⽐较排序算法,⽤于对x及y坐标排序,这并不增加其时间复杂度。
因此是可⾏的。
在分治算法中,设置划分区间的下限为3,即当区间内元素个数⼩于等于3时,不再使⽤分治。
在该设定下分为三种情况,元素数为1时,Min设为⽆穷。
元素数为2时,计算两点间距离并返回。
元素数为3时,⼀共计算三次距离,并取其最⼩值。
分治算法本⾝的思想为将分治与中线区间写在⼀个函数中,边界点的情况抛出,边界情况即元素数⼩于等于3时。
空间最近点对的计算机算法研究
将集合 S 分割 为 S 1 和 S2 两个半 平面区 域中的子 集, 递归地 分别在 S1 和 S2 上找出具有最小距离的点对 d1( p 1 , p 2 ) 和 d2 ( q1 - q2 ) , 并设 d = min{ d1 , d2 } 。用 P1 和 P 2 分 别表示 在直
线 L 左边 和右边 与其距离 在 d 范 围的点 构成的 两个垂直 长 条平面区域, P 1 : { p | | m- x (p ) | # d ∃p P 1 } ; P 2 : { q| | x ( q) - m| # d ∃q P2 } 。 分析可以知道, S 中的最近点对的距离 或者是 d , 或者是 某个 { p , q} 点对的距离, 其中 p P1 , q P 2 。如果{ p , q} 是 S 中的 最近点对, 则必有 distance( p , q) < d。对于 P 1 中的任意 一点 p , 满足这个条件的 P 2 中的点 q 一定落在一个 d % 2d 的 矩形 R 中; 可以证明在矩 形 R 中 最多 只有 6 个 S 中 的点 作为 P1 中点 p 的最近点对的候选者。 因此很 容易在 O ( n) 时间 内进 行处理。在进行分 治处 理之 前需 要对 集合 S 中 点的 坐标 采 用预排序技术, 预先将 n 个点依 次按照 坐标排 序。分治算 法 中只对排好序的序列做 一次线性扫描, 即可完成合并。因此, 平面最近点对算法耗费的计算时 间 T ( n) 也满足递归方程, 可 以在 O( n* log n) 时间内完成。
∋ 233 ∋
p 2 } 和{ q1 , 并设 d= min { d1 , d2} 。如果集合 S 中的最近点对的距离小于 d , 则这两个 点 p 3 、q3 必定分别属于子集 S1 和 S2 。即 S 中 的最近点对的 距离或者是 d , 或者是某个{ p 3 , q3 } 点对的距离, 其中 p 3 S1 , q3 S2 , 如图 1 所示。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一、算法分析
该算法的问题描述为:给定二维平面上的点集,求解距离最近的两个点,并计算出两点间的距离。
解决问题最初的思路为穷举法。
对所有两点间的组合计算其距离。
然后对其进行比较,找出最小值即可。
不过这样做的缺点是时间复杂度和空间复杂度十分庞大,消耗巨量资源。
如有n个点的平面上,计算的复杂度能达到n*n。
因此设计出一个高效的算法来代替穷举法是有现实意义的。
在思考问题的过程中,可以考虑使用分治法的思想,以x,y中x坐标作为划分区间的标准。
将平面点集一分为二。
求解其中的最小点对。
由此产生的问题为划分点附近两个区间中两点的距离可能小于各自区间中的最小值,产生了纰漏。
因此在在分治的过程中,加入分界线附近的点对最小值求解函数。
分界线区域内区间的选取标准为d。
其中d为左半区间和右半区间的最小值中的较小值。
在具体实现中,首先建立一个空数组存放按y坐标排序的点集,判断两个相邻点之间的y坐标差值,若大于d,则两点间距离一定大于d,可以直接跳过,继续判断下一个点对。
若小于d,则继续计算两点间的实际距离,若大于d,则跳过,小于d,将最小值更新为该点对距离。
二、算法实现
该算法的具体实现使用了两种求解方法,穷举法和分治法。
其中,穷举法用于判断最近点对算法实现结果的正确性。
算法使用的数据结构为数组,其中为了简单起见,将x轴坐标与y轴坐标分别存入两个数组,并新建一个数组record[],记录数组y的元素下标,用于绑定x坐标对应的y坐标。
在设计过程中使用到了比较排序算法,用于对x及y坐标排序,这并不增加其时间复杂度。
因此是可行的。
在分治算法中,设置划分区间的下限为3,即当区间内元素个数小于等于3时,不再使用分治。
在该设定下分为三种情况,元素数为1时,Min设为无穷。
元素数为2时,计算两点间距离并返回。
元素数为3时,一共计算三次距离,并取其最小值。
分治算法本身的思想为将分治与中线区间写在一个函数中,边界点的情况抛出,边界情况即元素数小于等于3时。
确保程序执行起始和终止位置的正确性。
三、实验结果
在实现过程中,选取点对数为5,输入不同的三组元素,进行算法正确性的验证。
1.(9,3) (7,10) (0,6) (5,8) (10,11)
实验结果如下图所示:
2.(34,5) (13,1) (5,62) (18,4) (32,15)
实验结果如下图所示:
3.(23,7) (47,19) (50,16) (35,54) (14,29) 实验结果如下图所示:。