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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
堆和二叉排序都是基于二叉树数据结构,但它们有以下几点不同: 1. 堆和二叉排序的排序方式不同。堆是一种特殊的数据结构,它可以被看做是一棵完全二叉树,且满足堆的性质:父节点的键值总是大于或等于(小于或等于)任何一个子节点的键值。而二叉排序是一种二叉树,它的每个节点的左子都比该节点小,右子都比该节点大。 2. 堆和二叉排序的插入和删除操作不同。堆的插入操作是将新元素插入到堆的末尾,然后通过上滤操作将其调整到合适的位置。删除操作是将堆顶元素删除,然后将堆的最后一个元素移到堆顶,再通过下滤操作将其调整到合适的位置。而二叉排序的插入和删除操作是通过比较节点的大小来进行的。 3. 堆和二叉排序的查找操作不同。堆只能查找堆顶元素,而不能像二叉排序那样进行中序遍历等操作。 4. 堆和二叉排序应用场景不同。堆主要用于实现优先队列数据结构,而二叉排序主要用于实现动态查找表等数据结构。 下面是一个堆的Python实现: ```python import heapq # 创建一个空堆 heap = [] # 插入元素 heapq.heappush(heap, 3) heapq.heappush(heap, 1) heapq.heappush(heap, 4) heapq.heappush(heap, 2) # 弹出堆顶元素 print(heapq.heappop(heap)) # 输出:1 # 查看堆顶元素 print(heap[0]) # 输出:2 ``` 下面是一个二叉排序Python实现: ```python class TreeNode: def __init__(self, val): self.val = val self.left = None self.right = None class BST: def __init__(self): self.root = None # 插入节点 def insert(self, val): if not self.root: self.root = TreeNode(val) else: self._insert(val, self.root) def _insert(self, val, node): if val < node.val: if not node.left: node.left = TreeNode(val) else: self._insert(val, node.left) else: if not node.right: node.right = TreeNode(val) else: self._insert(val, node.right) # 查找节点 def search(self, val): return self._search(val, self.root) def _search(self, val, node): if not node: return False elif val == node.val: return True elif val < node.val: return self._search(val, node.left) else: return self._search(val, node.right) # 创建一个二叉排序 bst = BST() # 插入节点 bst.insert(3) bst.insert(1) bst.insert(4) bst.insert(2) # 查找节点 print(bst.search(2)) # 输出:True print(bst.search(5)) # 输出:False ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

笨猪起飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值