1. 程式人生 > >凸包問題的分治演算法及python實現

凸包問題的分治演算法及python實現

利用分治思想處理凸包問題。
劃分:將點集S中的資料按橫座標排序,選出橫座標最小的點A和縱座標最小的點B,AB的連線將S劃分為兩個子集,位於(AB) 上方的集合S1和位於(BA) 上方的集合S2。

遞迴求解:遞迴呼叫演算法求S1的凸包和S2的凸包,遞迴演算法中找出S1中使∆ABC面積最大的點C,則點C一定位於S1的凸包上,繼續以點AC和CB作為連線劃分S1。

合併:通過上述方法找到的凸包上的點直接合並,最後使用蠻力演算法中的輸出方法逆序輸出點即可。

隨機點集S生成部分與蠻力演算法相同

分治演算法中遞迴部分程式碼如下:

def dealleft(first,final,lis,temp):
    #temp用來標記位於凸包上的點
    max=0
index=-1 #處理first到final的上方,得到使first,final,i 三點組成的三角形面積最大的點i if first<final: for i in range(first,final): #獲得first,final,i 的座標 firstcoordinate=lis[first] finalcoordinate=lis[final] icoordinate=lis[i] firstx=firstcoordinate[0
] firsty = firstcoordinate[1] finalx=finalcoordinate[0] finaly = finalcoordinate[1] ix=icoordinate[0] iy = icoordinate[1] #計算first,final,i 三點組成的三角形面積 triangle_area=firstx * finaly + ix * firsty + finalx * iy - ix * finaly - finalx * firsty - firstx * iy if
triangle_area>max: max=triangle_area index=i # 處理first到final的下方,得到使first,final,i 三點組成的三角形面積最大的點i else: for i in range(final,first): firstcoordinate = lis[first] finalcoordinate = lis[final] icoordinate = lis[i] firstx = firstcoordinate[0] firsty = firstcoordinate[1] finalx = finalcoordinate[0] finaly = finalcoordinate[1] ix = icoordinate[0] iy = icoordinate[1] triangle_area = firstx * finaly + ix * firsty + finalx * iy - ix * finaly - finalx * firsty - firstx * iy if triangle_area > max: max = triangle_area index = i if index!=-1: temp[index]=1 dealleft(first,index,lis,temp) dealleft(index,final,lis,temp)

接下來是演算法的主程式部分,程式碼如下:

def divide(lis,n):
    starttime = datetime.datetime.now()
    # temp用來標記位於凸包上的點
    temp = {}
    # lis_con_new為凸包集合
    lis_con_new = []
    if n==3:
        return  lis
    for i in range(n):
        temp[i]=0
    lis_con=copy.deepcopy(lis)
    lis_con.sort()
    temp[0]=1
    temp[n-1]=1
    dealleft(0,n-1,lis_con,temp)
    dealleft(n-1,0,lis_con,temp)
    for i in temp:
        if temp[i]==1:
            lis_con_new.append(lis_con[i])
    endtime = datetime.datetime.now()
    print "分治時間---",(endtime - starttime)
    return  lis_con_new

分治演算法在點集數500、1000、2000、3000、4000的情況下得到演算法執行時間(秒),繪製成如下圖所示折線圖,可以看出在資料集較大的情況下,分治演算法執行時間仍在毫秒水平,保持較好的效能。其中在資料從2000增加至3000的過程中,演算法執行時間有些許減少。

分治效能