1. 程式人生 > 實用技巧 >資料結構與演算法(24)——優先佇列和二叉堆

資料結構與演算法(24)——優先佇列和二叉堆

  • 優先佇列Priority Queue

性質:隊首出隊。高優先順序的資料項在隊首,而低優先順序的資料項則排在後面。

實現優先佇列額經典方案是二叉堆資料結構。二叉堆能夠優先將佇列的入隊和出隊複雜度都保持在O(log n)

  • 二叉堆Binary Heap實現優先佇列

BinaryHeap():建立一個空二叉堆物件;

insert(k):將新key加入到堆中;

findMin():返回堆中的最小項,最小項仍保留在堆中;

delMin():返回堆中的最小項,同時從堆中刪 除;

isEmpty():返回堆是否為空;

size():返回堆中key的個數;

buildHeap(list):從一個key列表建立新堆

用非巢狀列表實現二叉堆。

平衡二叉樹:樹根左右子樹擁有相同數量的節點。

完全二叉樹:葉節點最多隻出現在最底層和次底層,而且最底層的葉節點都連續集中在最左邊, 每個內部節點都有兩個子節點,最多可有1個節點例外。

完全二叉樹的列表實現及性質:如果節點的下標為p,那麼其左子節點下標為2p, 右子節點為2p+1,其父節點下標為p//2

  • 堆次序Heap Order

任何一個節點x,其父節點p中的key均小 於x中的key

  • 二叉堆的實現

inserKey:當新增一個新key時,新key加在列表末尾,顯然無法保持“堆”次序 雖然對其它路徑的次序沒有影響,但對於其到根的路徑可能破壞次序。因此需要將完全二叉樹最左邊的葉子節點“上浮”到其正確的位置。

delMin():移走整個堆中最小的key:根節點heapList[1] 為了保持“完全二叉樹”的性質,只用最後一個 節點來代替根節點 。這麼簡單的替換,還是破壞了“堆”次序 ,將新的根節點沿著一條路徑“下沉”, 直到比兩個子節點都小,直到比兩個子節點都小。

class BinHeap:
    def __init__(self): #初始化
self.heapList
= [0] self.currentSize = 0 def insert(self, k): self.heapList.append(k)
#新key新增到末尾 self.currentSize = self.currentSize + 1 self.percUp(self.currentSize) #新key上浮 def percUp(self, i): #沿路徑向上 while i // 2 >0: #沿著路徑往上遍歷其父節點 if self.heapList[i] < self.heapList[i // 2]: tmp = self.heapList[i // 2] self.heapList[i //2] = self.heapList[i] self.heapList[i] = tmp i = i // 2 def percDown(self, i): #交換下沉 while(i * 2) <= self.currentSize: mc = self.minChild(i) if self.heapList[i] > self.heapList[mc]: tmp = self.heapList[i] self.heapList[i] = self.heapList[mc] self.heapList[mc] = tmp i = mc def minChild(self, i): if i * 2 + 1 > self. currentSize: #唯一一個子節點 return i * 2 else: #返回較小的 if self.heapList[i * 2] < self.heapList[ i * 2 + 1]: return i * 2 +1 def delMin(self): retval = self.heapList[1] #移走堆頂 self.heapList[1] = self.heapList[self.currentSize] #把最後一個搬到根節點上來 self.currentSize = self.currentSize - 1 #pop掉原來的根節點 self.heapList.pop() self.percDown(1) return retval def buildHeap(self, alist): #下沉 i = len(alist) // 2#從最後節點的父節點開始下沉 self.currentSize = len(alist) self.heapList = [0] + alist[:] print(len(self.heapList), i) while (i > 0): print(self.heapList, i) self.percDown(i) i = i - 1 print(self.heapList, i)