python实现优先队列

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python实现优先队列相关的知识,希望对你有一定的参考价值。

学习了堆排序,使用python实现了一个优先队列结构,记录一下实现过程:

用一个python的list来表示堆结构,将list作为参数传入构造函数中,然后在构造函数中建堆:

class prioQueue:
    def __init__(self, elist=[]):
        self._elems = list(elist)
        if elist:
            self.buildheap()

堆一般都是一个完全二叉树,那么根据完全二叉树的性质,一个节点i的左子节点为i+1,右子节点为i*2+1,以最小堆为例,根节点一定是最小值,优先队列必须保证每次弹出的值都是最小的。建堆过程是一个递归的过程,首先拿出list中第一个元素,一个元素必然是一个堆,接下来从list最后拿2个元素分别作为2个子堆,若要将第一个元素这个堆和最后2个元素所构成的子堆合并成一个堆,那么就要保证堆顶的值最小,先判断左右2个子堆的大小,然后用第一个元素和较小的比较,若小,则不变,若大,则将元素与子堆那个元素调换位置,这样就形成了1个3个元素的最小堆,之后再从list中拿出第二个元素,从排序好的堆中一次进行这个步骤,若较小,则跳出循环拿出下一个元素,若较大则交换2个比较的元素,再用这个元素与2个子节点的元素进行比较,直到遍历了整个二叉树都没有更大的元素,那么这个元素就将放在元素的最末尾。这便是一个从堆顶即二叉树根节点开始向下扫描的过程,先定义这个siftDown方法:

def siftdown(self, e,begin, end):
        elems, i, j, = self._elems, begin , begin*2+1

e为要排序的元素,变量i 储存我们开始排序的位置,为了不浪费空间,begin参数来作为排序好及位排好的元素list中的索引,所以一开始是0之后递增,end参数代表着堆元素的个数,也就是len(list)。

然后我们用elems变量保存数组 i作为排序元素的指针 j为i的左子树 进行循环。只要j没有到最后就循环下去。

while j < end:

然后先比较左右子树,使用较小的子树来和插入的e做比较,若e小于它那么就找到位置,否则调换位置继续与换位置后的左右子树进行比较,i位置即是元素e所在的位置:

if j+1<end and elems[j+1] < elems[j]:
                j = j + 1         
            if e < elems[j]:
                break
            elems[i] = elems[j]
            i, j = j , 2*j+1
        elems[i] = e

对list的每一个元素都进行这样的一个向下扫描,就可以完成一个建堆的过程,得到一个最小堆:

    def buildheap(self):
        end = len(self._elems)
        for i in range(end//2,-1,-1):
            self.siftdown(self._elems[i],i,end)
        return self._elems

 

以上是关于python实现优先队列的主要内容,如果未能解决你的问题,请参考以下文章

基于event 实现的线程安全的优先队列(python实现)

python实现优先队列

数据结构:优先队列 基于list实现(python版)

华为OD机试真题Python实现打印文件真题+解题思路+代码(2022&2023)

Python:在优先队列实现中使用我的堆

基于condition 实现的线程安全的优先队列(python实现)