堆是一種完全二叉樹,堆排序是一種樹形選擇排序,利用了大頂堆堆頂元素最大的特點,不斷取出最大元素,並調整使剩下的元素還是大頂堆,依次取出最大元素就是排好序的列表。舉例如下,把序列[26,5,77,1,61,11,59,15,48,19]排序,如下:
代碼如下:
def fixUp(a): #在堆尾加入新元素,fixUp恢複堆的條件k=len(a)-1while k>1 and a[k//2]<a[k]:a[k//2],a[k]=a[k],a[k//2]k=k//2def fixDown(a): #取a[1]返回的值,然後把a[N]移到a[1],fixDown來恢複堆的條件k=1N=len(a)-1while 2*k<=N:j=2*kif j<N and a[j]<a[j+1]: j+=1if a[k]<a[j]:a[k],a[j]=a[j],a[k]k=jelse:breakdef insert(a,elem):a.append(elem)fixUp(a)def delMax(a):maxElem=a[1]N=len(a)if N<=1:print('There\'s none element in the list')return -1if N==2:return a[1]else:a[1]=a.pop()fixDown(a)return maxElemdata=[-1,] #第一個元素不用,佔位insert(data,26)insert(data,5)insert(data,77)insert(data,1)insert(data,61)insert(data,11)insert(data,59)insert(data,15)insert(data,48)insert(data,19)result=[]N=len(data)-1for i in range(N):print(data)result.append(delMax(data))print(result)
fixUp函數用於向列表的尾部添加一個新的元素,然後調整成大頂堆;fixDown函數用於取出大頂堆最大的元素後,把列表尾部的元素放到堆頂位置,然後再調整成大頂堆;insert函數是每次插入一個新的元素並調整成為大頂堆;delMax函數把最大的元素返回出來並把剩下的元素調整成為大頂堆。 輸出如下:
[-1, 77, 61, 59, 48, 19, 11, 26, 1, 15, 5][-1, 61, 48, 59, 15, 19, 11, 26, 1, 5][-1, 59, 48, 26, 15, 19, 11, 5, 1][-1, 48, 19, 26, 15, 1, 11, 5][-1, 26, 19, 11, 15, 1, 5][-1, 19, 15, 11, 5, 1][-1, 15, 5, 11, 1][-1, 11, 5, 1][-1, 5, 1][-1, 1][77, 61, 59, 48, 26, 19, 15, 11, 5, 1]
前面的輸出是不斷取出最大元素後的大頂堆,由於是完全二叉樹,根據列表可以自己寫出大頂堆的樹形結構,就不在這裡贅述,最後一行是排好序的列表。
轉載請註明: