1.问题
在二维平面上的n个点中,找出最接近的一对点
2.解析
已知集合S中有n个点,使用分治法的思想就是将S进行拆分,分为2部分求最近点对。算法每次选择一条垂线L,将S拆分左右两部分为SL和SR,( L一般取点集S中所有点的中间点的x坐标来划分,这样可以保证SL和SR中的点数目各为n/2 否则以其他方式划分S,有可能导致SL和SR中点数目一个为1,一个为n-1,不利于算法效率,要尽量保持树的平衡性 )
依次找出这两部分中的最小点对距离:δL和δR,记SL和SR中最小点对距离δ = min{δL,δR}
3.设计
def Closest_pair(points)
BEGIN
length=points.length // 获取数组长度
qsort(points,points+length,x) // 以x为标准对点集合points进行快速排序
ClosestPair(Point points[], int length, Point &a, Point &b) // 求最近点对及最近点对距离
END
def ClosestPair(Point points[], int length, Point &a, Point &b)
BEGIN
if length< 2
then
return infinite // 如果数组长度小于2 返回无穷大
else if length = 2
then
return distance(points[0],points[1] // 如果数组长度等于2 返回该两点的距离
else // 数组长度大于3
then
mid = points.mid // 获取中线
pts1 = points(<=mid) // 存储两个集合点
pts2 = points(>mid)
d1 = ClosestPair(pts1, length / 2, a1, b1); //分治求解左半部分子集的最近点
d2 = ClosestPair(pts2, length - length / 2, a2, b2); //分治求解右半部分子集的最近点
d = min(d1,d2)
// merge 合并子集解
pts3 = points(abs(x-mid<d) // 存储在2d之前的点
for(each points : pits3)
找到points在对侧相邻的6个点 依次计算距离
判断是否更新距离distance 和 点a,b
END
4.分析
快速排序过程
对点集S的点坐标进行升序快速排序,复杂度为O(nlogn)
分治过程
接下来在分治过程中,对于每个S’yL中的点,都需要与S’yR中的6个点进行比较
O(n)= 2O(n/2) + (n/2)*6 (一个点集划分为左右两个点集,时间复杂度为左右两个点集加上中间区域运算之和)
带入主定理求解即可得到世界复杂度
因此总的时间复杂度为O(nlogn),比蛮力法的O(n2)要高效
5.源码
[github源码地址]
https://github.com/henryzhang6686/myAlgorithmCode