利用二叉堆实现优先级队列(python实现)

文章介绍了优先级队列的概念,它是一种基于元素优先级的队列,常通过二叉堆来高效实现。enqueue方法通过追加元素并使用percUp方法维护堆的结构,而dequeue方法则移除最小元素并用percDown恢复堆序。堆的构建和维护对于算法效率至关重要。
摘要由CSDN通过智能技术生成

       队列有一个重要的变体,叫作优先级队列。和队列一样,优先级队列从头部移除元素,不过元素的逻辑顺序是由优先级决定的。优先级最高的元素在最前,优先级最低的元素在最后。因此,当一个元素人队时,它可能直接被移到优先级队列的头部。
       你或许可以想到一些使用排序函数和列表实现优先级队列的简单方法。但是,就时间复杂度而言,列表的插人操作是0(n),排序操作是O(nlogn)。其实,效率可以更高。实现优先级队列的经典方法是使用叫作二叉堆的数据结构。二叉堆的人队操作和出队操作均可达到0(logn)。
       首先实现enqueue方法。将元素加入列表的最简单、最高效的方法就是将元素追加到列表尾。追加操作的优点在于,它能保证完全树的性质,但缺点是很能会破坏堆的结构性质可以写一个方法,通过比较新元素与其父元素来重新获得堆的结构性质。如果新元素小于其父元素,就将二者交换。


 

       注意,将元素往上移时,其实是在新元素及其父元素之间重建堆的结构性质。此外,也保留
了兄弟元素之间的堆性质。当然,如果新元素很小,需要继续往上一层交换。下面列出了percUp方法的代码,该方法将元素一直沿着树向上移动,直到重获堆的结构性质。我们使用整数除法计算任意节点的父节点。就当前节点而言,父节点的下标就是当前节点的下标除以2。

class priority_queue:
    def __init__(self,heap):
        self.heap=heap
    def percup(self,i):
        while i//2>0:
            if self.heap[i]<self.heap[i>>1]:
                temp=self.heap[i]
                self.heap[i]=self.heap[i>>1]
                self.heap[i>>1]=temp
            i=i>>1

向二叉堆中添加新元素

    def enqueue(self,k):
        self.heap.append(k)
        self.percup(len(self.heap)-1)

定义enqueue方法后,就可以编写dequeue方法。既然堆的结构性质要求根节点是树的最小元素,那么查找最小值就很简单。dequeue方法的难点在于,如何在移除根节点之后重获堆的结构性质和有序性。可以分两步重建堆。第一步,取出列表中的最后一个元素,将其移到根节点的位置。移动最后一个元素保证了堆的结构性质,但可能会破坏二叉堆的有序性。第二步,将新的根节点沿着树推到正确的位置,以重获堆的有序性。


 

 为了维持堆的有序性,只需交换根节点与它的最小子节点即可。重复节点与子节点的交换过程,直到节点比其两个子节点都小。

    def percdown(self,i):
        while (i<<1)<=len(self.heap)-1:
            num=self.minChild(i)
            if self.heap[i]>self.heap[num]:
                temp=self.heap[i]
                self.heap[i]=self.heap[num]
                self.heap[num]=temp
    def minChild(self,i):
        if i<<1==len(self.heap)-1:
            return i<<1
        elif self.heap[i<<1]<self.heap[i<<1|1]:
            return i<<1
        return i<<1|1

从二叉堆中删除最小的元素即出队操作

    def dequeue(self):
        temp=self.heap[1]
        self.heap[1]=self.heap[-1]
        self.heap.pop()
        self.percdown(1)
        return temp

根据元素列表构建原始堆

    def build_priority_queue(self):
        self.heap.insert(0,0)
        for i in range((len(self.heap)-1)>>1,0,-1):
            self.percdown(i)

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值