Python 内置优先队列PriorityQueue 高级餐厅用餐场景展示

1,095 阅读3分钟

「这是我参与2022首次更文挑战的第15天,活动详情查看:2022首次更文挑战」。

正式的Python专栏第64篇,同学站住,别错过这个从0开始的文章!

前面学委说要把内置队列都撸一撸,前面展示了有简单的先进后出,先进先出队列。

今天把优先队列先展示了。

PriorityQueue

这是一个懂得分辨轻重缓急的队列。 之前FIFO/FILO这些都是按照放入顺序,先放进去的要么先出队,要么后面出队。

实际应用场景跟我们日常类似,比如我们去一个高级餐厅吃饭。

通常他们会设置会员等级,比如常客VIP,或者那种高级VIP(VVIP),这些入队。

前台服务人员就会根据客户登记安排客户进场。

这时候优先队列就派上用场。

优先队列可以放入元素格式如下:


q = PriorityQueue()
# 二元组(优先级数,数据 )
q.put((3, '小白'))

下面是模拟整个队列排队:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2022/2/14 11:13 下午
# @Author : LeiXueWei
# @CSDN/Juejin/Wechat: 雷学委
# @XueWeiTag: CodingDemo
# @File : priorityqdemo.py
# @Project : hello

from queue import PriorityQueue

q = PriorityQueue()

q.put((3, '小白'))
#后到
q.put((2, '雷学委'))
#最后到
q.put((1, '小花'))

while not q.empty():
    next_item = q.get()
    print("🐰 欢迎 %s 用餐:" % str(next_item))

首先,小白没有VIP先到拿号了。 然后学委,小花陆续去餐厅排队。

直接运行代码,可以看到小花同学最后到场,但是她缺第一个进去餐厅内堂用餐了。

没办法,她是VVIP,级别最高(第三个元素的数值最小)所以放到最前面了。

效果图如下:

屏幕快照 2022-02-14 下午11.47.28.png

所以就很‘合理’(没办法,谁叫你去高级餐厅排队,去个普通的餐厅,我们就用普通FIFO队列来管理用餐秩序了)。

优先队列怎么排队的?

打开queue这个库直接看到PriorityQueue这个类源码:

屏幕快照 2022-02-14 下午11.52.11.png

太简单了,直接继承了Queue父类。

不过我们看到优先队列覆盖了_put方法,用了heappush方法来放元素到二叉堆(这个是在heapq内置库里面的一个方法,也有取元素的实现)。

def heappush(heap, item):
    """Push item onto heap, maintaining the heap invariant."""
    heap.append(item)
    _siftdown(heap, 0, len(heap)-1)
    

headpush内部直接把新入队的元素放到队尾(前面heap=[])

然后执行下面的方法摆放元素:

def _siftdown(heap, startpos, pos):
    newitem = heap[pos]
    # Follow the path to the root, moving parents down until finding a place
    # newitem fits.
    while pos > startpos:
        parentpos = (pos - 1) >> 1
        parent = heap[parentpos]
        if newitem < parent:
            heap[pos] = parent
            pos = parentpos
            continue
        break
    heap[pos] = newitem

这里使用[最小二叉堆(baike.baidu.com/item/%E6%9C…) ,通过不断与父节点对比(父节点的位置为parentpos = (pos - 1) >> 1)。

循环比对,如果新加元素小于父节点,当前新加节点上移(也就是父节点下移到新节点每次放入的新位置)

直到找到一个父节点是小于新节点值的位置,停止移动,入队操作完毕。

这一段比较烧脑,先解释这个入队。后面再做一个图形展示一下。

总结

优先队列,就像高级餐厅或者银行排队VIP/VVIP这种,特殊人群特殊安排。

内部实现用了二叉树这个数据结构,后面学委再做图展示。

前篇学委说了这个, 再次放在一起,比对回顾:

后进先出队列,很像超市货柜,后面放的物品,先被消费者看到。

先进先出队列,就像大家排队体检,排队打饭一样。肯定是先到的先安排。

优先队列,就像高级餐厅或者银行排队VIP/VVIP这种,特殊人群特殊安排。

喜欢Python的朋友,请关注学委的 Python基础专栏 or Python入门到精通大专栏

持续学习持续开发,我是雷学委!
编程很有趣,关键是把技术搞透彻讲明白。
欢迎关注微信,点赞支持收藏!