分治法求最近点对实验

分治法求最近点对

实验概述

  1. 对于平面上给定的N个点,给出所有点对的最短距离,即,输入是平面上的N个点,输出是N点中具有最短距离的两点。

  2. 要求随机生成N个点的平面坐标,应用蛮力法编程计算出所有点对的最短距离。

  3. 要求随机生成N个点的平面坐标,应用分治法编程计算出所有点对的最短距离。

实验思路

首先明确分治法的一大特点就是大化小,不知道从哪里下手时可以先思考最小的情况。

最小情况:只有一个点返回无穷大,两个点返回两点距离,三点两两比较返回最小。不过事实上,定下一个阙值例如20,在小于等于20个点时直接找到最小边返回是效率更高的做法。
分治法求最近点对实验_第1张图片
多于3点时把点击分为左右两个点集继续递归。所以预处理时需要先将点集按x排序,每次取中间点作为划分。
分治法求最近点对实验_第2张图片
合并时,探索两点集交汇处有无更短点对。首先我们得到左右两部分最短距离dL, dR,这些有可能的点集中在中线左右d = min(dL, dR)的部分。
分治法求最近点对实验_第3张图片
为了使合并时间为线性,必须将挑出这条窄缝中的点的时间限制在线性。办法是对所有点集做一次对y的排序,每次只需遍历该对y排序的点集,找出在窄缝中间的点;然后,自下往上,对每一个点,探索其上的最多6个点。

然而,如果只有一个大小为n的对y排序了的点集,每次遍历一次就需要操作n次。对于一个一百万大小的点集就是每次执行一次一百万的遍历,很费时间。既然我们是分治,那就容易想到一个分治的排序算法:归并排序。先递归得到左右两边有序的点集,在合并的时候做一次归并,得到一个规模较小的点集,减少遍历的时间。

为什么最多6个点呢?首先,对于该点下面的点我们不用看了,因为前面已经看过;其次,对于纵坐标距离该点d以上距离的点也不用看了,这就意味着只需要看以该点为底的2d*d的矩形之内的点。假设要探索的点在左半边,由于在左、右两个点集中的点,两两之间的距离都不小于d,故极限情况下在右半边的点有4个(中线上的点也算在右边),左半边则最多再放2个。这个矩形内最多放6个点(不包含要探索的点)。假设要探索的点在右半边,同理也是最多看6个点。
分治法求最近点对实验_第4张图片
最后放一个链接:分治法与蛮力法求最近点对问题(分治法时间复杂度O(nlogn))

你可能感兴趣的:(算法)