空间最小距离点对——python

  1. 请参考教材98页,算法6.6,先来个常规算法,复杂度为n的平方,结合Python的优势,代码整短点,顺便绘制下图形,算法思路简单,不多说了,注意陷阱。
  2. 上代码了:
#coding=utf-8
import math
import matplotlib.pyplot as plt
def closestpair_simple(X, n):
    #对于n个数据点,计算n(n-1)/2个数就可以了
    dist = [[distance(X[i], X[j]), i, j] for i in range(len(X)) for j in range(i+1,len(X))]
    return min(dist)[0], [min(dist)[1], min(dist)[2]]
def distance(a, b):
    return math.sqrt(math.pow(a[0]-b[0], 2)+math.pow(a[1]-b[1], 2))
if __name__ == "__main__": 
    points = [(2,3), (10, 1), (3, 25), (23,15), (18,3), (8,9), (12,30), (25,30), (9,2), 
             (13,10), (3,4), (5,6), (22,32), (5,32), (23,9), (19,25), (14,1), (11,25), (26,26),
             (12,9), (18,9), (27,13), (32,13)]
    print (closestpair_simple(points, len(points)))
    #绘制这些点
    x = [points[i][0] for i in range(len(points)) ]
    y = [points[j][1] for j in range(len(points))]
    plt.plot(x, y, 'ro')
    plt.plot([2, 3], [3, 4]) #绘制两个点之间的连线,多了的时候可以循环
    plt.show()
  1. 绘制的图形:
    空间最小距离点对——python_第1张图片
  2. 感兴趣的童鞋可以把点的坐标自己标上,不过没啥用,本身就能看得出来。
  3. 另外一种是分治算法,里面的难点就是跨界解怎么求?当然了点序列怎么分成子问题,分割也是个麻烦的问题。就比如下面图示这种情况:
    空间最小距离点对——python_第2张图片
  4. 详细的难点课堂上会讲解,记得预习即可。分治法求解代码贴上先:
import math
def closest(P, n):
    X = list(P)
    Y = list(P)
    X.sort()
    Y = sort_y(Y)
    return closest_pair(X, Y, n)
def sort_y(Y):
    return sorted(Y, key=lambda last:last[-1])
def closest_pair(X, Y, n):
    if n <= 3:
        return brute_force(X, n)
    mid = n / 2
    Y_left = []
    Y_right = []
    for p in Y:
        if p in X[:mid]:
            Y_left.append(p)
        else:
            Y_right.append(p)
    dis_left = closest_pair(X[:mid], Y_left, mid)
    dis_right = closest_pair(X[mid:], Y_right, n-mid)
    min_dis = min(dis_left, dis_right)
    strip = []
    for (x, y) in Y:
        if abs(x-X[mid][0]) < min_dis:
            strip.append((x, y))
    return min(min_dis, strip_closest(strip, min_dis))
def brute_force(X, n):
    min_d = distance(X[0], X[1])
    for i, (x, y) in enumerate(X):
        for j in range(i+1, n):
            if distance(X[i], X[j]) < min_d:
                min_d = distance(X[i], X[j])
    return min_d
def distance(a, b):
    return math.sqrt(math.pow((a[0]-b[0]), 2)+math.pow((a[1]-b[1]), 2))
def strip_closest(strip, d):
    min_d = d
    for i, (x, y) in enumerate(strip):
        for j in range(i+1, 6):
            if i + j < len(strip):
                temdis = distance(strip[i], strip[j])
                if temdis < min_d:
                    min_d = temdis
    return min_d
if __name__ == "__main__":
    points = [(2,3), (10, 1), (3, 25), (23,15),
             (18,3), (8,9), (12,30), (25,30),
             (9,2), (13,10), (3,4), (5,6),
             (22,32), (5,32), (23,9), (19,25),
             (14,1), (11,25), (26,26), (12,9),
             (18,9), (27,13), (32,13)]
    print (closest(points, len(points)))   

你可能感兴趣的:(作业题)