算法与分析实验五:最近对问题

1. 问题

前提:令P为笛卡儿平面上n>1个点构成的集合。简单起见,假设集合中的每个点都不一-样。
我们还假设这些点是按照其x轴坐标升序排列的。(如果不是这样,可以事先用类似合并排序这样的高效算法对其排序。)为了更加方便,我们还可以按照点的y轴坐标在另一个列表中进行升序排列,并将这个列表示为Q。
当2≤n≤3时,问题就可以通过蛮力算法求解。
当n>3时,可以利用点集在x轴方向上的中位数m,在该处作一条垂线, 将点集分成大小分别为 「n/2]和[n/2」的两个子集P和Pro即使得其中「n/27个点位于线的左边或线上,[n/2 ]个点位于线的右边或线上。然后就可以通过递归求解子问题P和P来得到最近点对问题的解。其中d,和d,分别表示在P和P中的最近对距离,并定义d = min{d,d}。

问题:最近对问题要求在包含有n个点的集合S中,找出距离最近的两个点。设 p1(x1,y1),p2(x2,y2),……,pn(xn,yn)是平面的n个点。
严格地说,最近点对可能不止一对,此例输出一对即可。

2. 解析

在这里插入图片描述

3. 设计

//实现求最近对距离
double Closest(point S[], int low, int high){
	double d1, d2, d3, d;
	int mid, i, j, index;
	point P[n];                   //存放点集合 P1和P2
	//如果只有两个点,返回这两个点间的距离
	if (high - low == 1) {
		return Distance(S[low], S[high]);	
	}	
	if (high - low == 2)	{//如果有三个点,求最近点对距离
		d1 = Distance(S[low], S[low + 1]);
		d2 = Distance(S[low + 1], S[high]);
		d3 = Distance(S[low], S[high]);
		if ((d1 < d2) && (d1 < d3))	return d1;
		else if (d2 < d3) return d2;
		else return d3;
	}
	mid = (low + high) / 2;				//计算中间点
	d1 = Closest(S, low, mid);			//递归求解子问题①
	d2 = Closest(S, mid + 1, high);		//递归求解子问题②
	if (d1 <= d2) d = d1;				//已下为求解子问题
	else d = d2;
	index = 0;
	for (i = mid; (i >= low) && (S[mid].x - S[i].x < d); i--)			//建立点集合P1
		P[index++] = S[i];
	for (i = mid + 1; (i <= high) && (S[i].x - S[mid].x < d); i++)		//建立点集合P2
		P[index++] = S[i];
	QuickSort(P, 0, index - 1);//对集合P1、P2按y坐标升	 
	//依次处理集合P1和P2中的点
	for (i = 0; i < index; i++)	{
		for (j = i + 1; j < index; j++)		{
			if (P[j].y - P[i].y >= d)		//超出y坐标的范围,点P[i]处理完毕
				break;
			else			{
				d3 = Distance(P[i], P[j]);
				if (d3 < d)
					d = d3;
			}
		}
	}
	return d;
}
 
//求两点之间距离
double Distance(point a, point b){
	return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}

4. 分析

时间复杂度:O(nlog2n)

5. 源码

https://github.com/moshang1113/Clostest-Pair

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值