平面最近点对算法的改进

实验内容:求平面最近点对

实验步骤

  1. 实现最邻近点对,先定义了一个Point结构体类,结构中包含了横纵坐标
  2. 用srand算法随机生成若干点的横纵坐标
  3. 写两个快速排序函数QsortxQsorty来实现对坐标x,y的排序,横纵坐标排序算法在分治算法之前进行处理,减少分治算法的时间复杂度。
  4. 分治算法:

第一类:只有一个点 return 最大距离

第二类:只有两个点,那么直接调用Distance()(计算两个点之间距离的函数),并把两个点记录下来;

第三类:如果点数为三个或以上,开始划分工作

  对按照x排好序的点取出其中的中位数,按照中位数来进行左右划分(再开两个Point点集pts1和pts2)

  递归调用分治算法函数,分别对左右两边的点集计算其最小距离,并记录形成最小距离的点

  对比左右两边,取出最小的距离和点

  以中位数横坐标为基准,将x坐标距离中位数的距离小于最小距离的点记录的在新点集中,并对该点集进行排序

  对于任意一个在新集合中的点,假设它处于左半边与他相距小于最小距离的点只有右边宽为distance,长为2distance(y-distancey+distance)。对该区域内所有点(不超过四个)进行挨个检验,该步骤时间复杂度为常数

 

关键函数:

//求出最近点对记录,并将两点记录再a、b中
float ClosestPair(Point points[], Point points1[], int length, Point& a, Point& b)
{
	float distance;        //记录集合points中最近两点距离 
	float d1, d2;           //记录分割后两个子集中各自最小点对距离
	int i = 0, j = 0, k = 0;       //用于控制for循环的循环变量
	Point a1, b1, a2, b2;     //保存分割后两个子集中最小点对

	if (length < 2)return NO_DISTANCE;    //若子集长度小于2,定义为最大距离,表示不可达
	if (length == 2)
	{
		a = points[0];
		b = points[1];
		distance = Distance(points[0], points[1]);
	}
	else
	{
		Point* pts1 = new Point[length];     //开辟两个子集
		Point* pts2 = new Point[length];

		float mid = points[(length - 1) / 2].x;  //排完序后的中间下标值,即中位数

		for (i = 0; i < length / 2; i++)
			pts1[i] = points[i];
		for (int j = 0, i = length / 2; i < length; i++)
			pts2[j++] = points[i];
		d1 = ClosestPair(pts1, points1, length / 2, a1, b1);           //分治求解左半部分子集的最近点  
		d2 = ClosestPair(pts2, points1, length - length / 2, a2, b2);    //分治求解右半部分子集的最近点  
		if (d1 < d2) { distance = d1; a = a1; b = b1; }
		else { distance = d2; a = a2; b = b2; }

		//求解跨分割线并在δ×2δ区间内的最近点对
        //points1是已经按照纵坐标排好序的结构体数组,所以当把处于中间2d宽度的点放到pts3数组中时,pts3数组也是排好序的
		Point* pts3 = new Point[length];
		for (i = 0, k = 0; i < length; i++)
			if (abs(points1[i].x - mid) <= distance)
				pts3[k++] = points1[i];

		for (i = 0; i < k; i++)
			for (j = i + 1; j <= i + 5 && j < k; j++)    //只需与有序的领接的的4个点进行比较
			{
				if (Distance(pts3[i], pts3[j]) < distance)
				{//如果跨分割线的两点距离小于已知最小距离,则记录该距离
					distance = Distance(pts3[i], pts3[j]);
					a = pts3[i];
					b = pts3[j];
				}
			}
	}
	return distance;
}

四个点分析:(参考论文:求平面点集最近点对的一个改进算法  周玉林)

只截取一部分图片,详情参考论文

 

本实验的改进之处为:

1. 对point点的纵坐标排序放在分治算法之前进行处理,减少分治算法的时间复杂度。

2. 对于可能存在的左边一点右边一点的最近点对的情况的检验中,由6个点改进为4个点,减少了计算量。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值