樹的應用之優先隊列和二叉堆的python實現

優先隊列

優先隊列的出隊與隊列一樣,均是從隊首出隊,但是在優先隊列內部,數據項的次序是由“優先級”來確定:高優先級的數據在隊首,低優先級的數據項則排在後面。

優先隊列的實現——二叉堆(Binary Heap)

二叉堆邏輯結構上像二叉樹,卻是用非嵌套的列表來實現。
二叉堆能夠將優先隊列的入隊和出隊複雜度都保持在O(log n)。
在這裏插入圖片描述
用非嵌套列表來實現二叉堆
(1)爲了使堆操作能保持在對數水平上,就必須採用二叉樹結構。
(2)若要使操作始終保持在對數級別,就需要始終保持二叉樹的“平衡”。:樹根左右子樹擁有數量相同的節點
基於此,我們採用“完全二叉樹”的結構來近似實現平衡。
在這裏插入圖片描述
完全二叉樹的性質:任何一個節點x,其父節點p中的key均小於x中的key。這樣,(1)根節點的key最小
(2)完全二叉樹中任何一條路徑,均是一個已排序的數列。

二叉堆的python實現

###二叉堆的初始化
class BinHeap:  
    def __init__(self):
        self.heaplist=[0]  #採用一個列表來保存堆數據,表首下標爲0的項無用,爲了後續整除,任保留它
        self.currentsize=0
## 建立二叉堆:從無序表生成“堆”
    def buildHeap(self,alist):
        i = len(alist) // 2
        self.currentSize = len(alist)
        self.heapList = [0] + alist[:]
        while (i > 0):
            self.percDown(i)
            i = i - 1
## insert(key)實現
    #新key加在隊列末尾,無法保持堆次序,因此需要將key沿着路徑上移到其正確位置。
    def insert(self,new_item):
        self.item_list.append(new_item)
        self.item_list[0]+=1
        self.upward_adjust(self.item_list[0])                    
    def upward_adjust(self,index):
        while index//2>0:
            if self.item_list[index]<self.item_list[index//2]:
                temp = self.item_list[index]
                self.item_list[index]=self.item_list[index//2]
                self.item_list[index//2]=temp
                index = index//2
            else:
                break
    ## delMin(key)實現
    #堆次序(最小堆)要求根節點是樹中最小的元素,因此很容易找到最小項。
    #比較困難的是移走根節點的元素後如何保持堆結構和堆次序,我們可以分兩步走。首先,用最後一個節點來代替根節點。移走最後一個節點保持了堆結構的性質。這麼簡單的替換,還是會破壞堆次序。那麼第二步,將新節點“下沉”來恢復堆次序。
    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
            else:
                return i * 2 + 1
    def delMin(self):
        item=self.heapList[1]
        self.heapList[1]=self.heapList[self.currentSize]
        self.currentSize-=1
        self.heapList.pop()
        self.percDown(1)
        return item
        
    ##判斷堆是否爲空
    def isEmpty(self):
        return 0 == self.item_list[0]

    # 返回堆中的項數
    def size(self):
        return self.item_list[0]
#測試例
bh = BinHeap()
bh.buildHeap([9,5,6,2,3])    
print(bh.delMin())

參考文獻:https://www.icourse163.org/learn/PKU-1206307812?tid=1450242471#/learn/content?type=detail&id=1214420560&cid=1218119415

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章