1. 队列基础概念回顾
在计算机科学中,队列(Queue)是一种遵循先进先出(FIFO)原则的线性数据结构。想象一下超市收银台前排队的人群——最早排队的人最先获得服务,这就是队列最形象的比喻。队列有两个基本操作:入队(enqueue)在队尾添加元素,出队(dequeue)从队头移除元素。
队列的实现通常需要维护两个指针:front指向队列头部,rear指向队列尾部。在C++中,标准库
cpp复制#include <queue>
using namespace std;
queue<int> q; // 声明一个整型队列
q.push(10); // 入队操作
int val = q.front(); // 获取队首元素
q.pop(); // 出队操作
队列的应用场景非常广泛:
- 操作系统中的进程调度
- 网络数据包传输
- 打印机任务管理
- 消息队列系统
- 广度优先搜索(BFS)算法
注意:基础队列在元素出队时严格按照入队顺序处理,无法根据元素的优先级进行调整,这在某些场景下会成为明显限制。
2. 优先队列的核心特性
优先队列(Priority Queue)是队列的一种变体,它不再遵循严格的FIFO原则,而是根据元素的优先级决定出队顺序。每次出队的都是当前队列中优先级最高的元素,就像医院急诊科会根据病人病情严重程度决定就诊顺序一样。
优先队列通常使用堆(Heap)数据结构实现,特别是二叉堆。堆是一种特殊的完全二叉树,满足堆属性:
- 最大堆:父节点的值大于等于子节点
- 最小堆:父节点的值小于等于子节点
这种结构保证了堆顶元素总是当前最大或最小的元素,使得获取最高优先级元素的操作可以在O(1)时间内完成。
优先队列的操作复杂度:
- 插入(push):O(log n)
- 取出最高优先级元素(pop):O(log n)
- 查看最高优先级元素(top):O(1)
在C++中,优先队列通过
cpp复制priority_queue<int> pq; // 默认最大堆
pq.push(3);
pq.push(1);
pq.push(4);
cout << pq.top(); // 输出4,当前最大值
pq.pop(); // 移除4
3. 优先队列的实现方式对比
3.1 数组无序实现
最简单的实现方式是使用无序数组:
- 插入:O(1) - 直接追加到数组末尾
- 取出最高优先级:O(n) - 需要线性扫描整个数组
这种实现适合插入频繁但很少取出最高优先级元素的场景。
3.2 数组有序实现
保持数组始终有序:
- 插入:O(n) - 需要找到正确位置并移动元素
- 取出最高优先级:O(1) - 直接取最后一个元素
适合取出操作频繁但很少插入的场景。
3.3 二叉堆实现
最常用的实现方式:
- 插入:O(log n) - 上浮操作
- 取出最高优先级:O(log n) - 下沉操作
在大多数情况下提供了最佳的综合性能。
