树的应用之优先队列和二叉堆的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

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