队列的使用【C++】
一、队列
在 C++ 中,队列(Queue)是一种先进先出(FIFO)的数据结构,即最早进入队列的元素将最先被移出。C++ 标准库提供了 std::queue
,这是一个容器适配器,基于其他容器(如 std::deque
或 std::list
)实现。此外,还有一种优先队列(Priority Queue),它允许元素按照优先级顺序出队。
1. std::queue
的使用
std::queue
是一个简单的 FIFO 队列,提供了基本的入队和出队操作。
包含头文件
#include <queue>
基本操作
- 入队(
push
):将元素添加到队列的尾部。 - 出队(
pop
):移除队列头部的元素。 - 访问队头(
front
):获取队列头部的元素。 - 访问队尾(
back
):获取队列尾部的元素。 - 检查队列是否为空(
empty
):返回队列是否为空。 - 获取队列大小(
size
):返回队列中的元素数量。
示例代码
#include <iostream>
#include <queue>int main() {std::queue<int> q;// 入队q.push(1);q.push(2);q.push(3);// 访问队头std::cout << "Front element: " << q.front() << std::endl; // 输出 1// 出队q.pop();// 访问新的队头std::cout << "Front element after pop: " << q.front() << std::endl; // 输出 2// 检查队列是否为空std::cout << "Is queue empty? " << (q.empty() ? "Yes" : "No") << std::endl; // 输出 No// 获取队列大小std::cout << "Queue size: " << q.size() << std::endl; // 输出 2return 0;
}
二、优先队列
2. std::priority_queue
的使用
std::priority_queue
是一个优先队列,它允许元素按照优先级顺序出队。默认情况下,优先队列是一个最大堆,即优先级最高的元素(值最大)将最先出队。
包含头文件
#include <queue>
基本操作
- 入队(
push
):将元素添加到优先队列中。 - 出队(
pop
):移除优先级最高的元素。 - 访问优先级最高的元素(
top
):获取优先级最高的元素。 - 检查队列是否为空(
empty
):返回队列是否为空。 - 获取队列大小(
size
):返回队列中的元素数量。
示例代码
#include <iostream>
#include <queue>
#include <vector>
#include <functional> // 包含 std::greaterint main() {// 默认是最大堆std::priority_queue<int> maxHeap;// 入队maxHeap.push(1);maxHeap.push(3);maxHeap.push(2);// 访问优先级最高的元素std::cout << "Top element (max heap): " << maxHeap.top() << std::endl; // 输出 3// 出队maxHeap.pop();// 访问新的优先级最高的元素std::cout << "Top element after pop (max heap): " << maxHeap.top() << std::endl; // 输出 2// 创建一个最小堆std::priority_queue<int, std::vector<int>, std::greater<int>> minHeap;// 入队minHeap.push(1);minHeap.push(3);minHeap.push(2);// 访问优先级最高的元素std::cout << "Top element (min heap): " << minHeap.top() << std::endl; // 输出 1// 出队minHeap.pop();// 访问新的优先级最高的元素std::cout << "Top element after pop (min heap): " << minHeap.top() << std::endl; // 输出 2return 0;
}
3. 自定义优先队列
如果需要自定义优先队列的行为,可以通过提供自定义的比较函数或比较对象来实现。
示例代码
#include <iostream>
#include <queue>
#include <vector>
#include <functional> // 包含 std::greaterstruct Compare {bool operator()(const int& a, const int& b) {return a > b; // 定义为最小堆}
};int main() {// 使用自定义比较函数std::priority_queue<int, std::vector<int>, Compare> customHeap;// 入队customHeap.push(1);customHeap.push(3);customHeap.push(2);// 访问优先级最高的元素std::cout << "Top element (custom heap): " << customHeap.top() << std::endl; // 输出 1// 出队customHeap.pop();// 访问新的优先级最高的元素std::cout << "Top element after pop (custom heap): " << customHeap.top() << std::endl; // 输出 2return 0;
}
4. 总结
std::queue
:一个简单的 FIFO 队列,适用于需要先进先出的场景。std::priority_queue
:一个优先队列,允许元素按照优先级顺序出队,默认是最大堆,但可以通过自定义比较函数或比较对象实现最小堆或其他行为。- 自定义优先队列:通过提供自定义的比较函数或比较对象,可以实现特定的优先级规则。
三、std::deque
(双端队列)
std::deque
(双端队列)是 C++ 标准库中的一个序列容器,它允许在两端进行高效的插入和删除操作。std::deque
的名字来源于 “double-ended queue”,即双端队列。它结合了数组和链表的优点,提供了快速的随机访问和动态大小调整。
1. 基本特性
- 动态大小:
std::deque
的大小可以动态变化,类似于std::vector
。 - 随机访问:支持通过索引快速访问元素,类似于数组。
- 两端操作:可以在队列的头部和尾部高效地插入和删除元素。
2. 基本操作
包含头文件
#include <deque>
创建和初始化
std::deque<int> dq; // 默认构造
std::deque<int> dq1 = {1, 2, 3, 4, 5}; // 初始化列表
std::deque<int> dq2(5, 10); // 5 个元素,每个值为 10
插入操作
- 在尾部插入:
push_back
- 在头部插入:
push_front
- 在指定位置插入:
insert
dq.push_back(6); // 尾部插入 6
dq.push_front(0); // 头部插入 0
dq.insert(dq.begin() + 2, 99); // 在索引 2 的位置插入 99
删除操作
- 从尾部删除:
pop_back
- 从头部删除:
pop_front
- 从指定位置删除:
erase
dq.pop_back(); // 删除尾部元素
dq.pop_front(); // 删除头部元素
dq.erase(dq.begin() + 2); // 删除索引 2 的元素
访问元素
- 随机访问:通过下标操作符
[]
或at
方法 - 头部元素:
front
- 尾部元素:
back
int first = dq.front(); // 访问头部元素
int last = dq.back(); // 访问尾部元素
int third = dq[2]; // 访问索引为 2 的元素
int third_safe = dq.at(2); // 安全地访问索引为 2 的元素,越界会抛出异常
其他操作
- 检查是否为空:
empty
- 获取大小:
size
- 清空:
clear
if (dq.empty()) {std::cout << "Deque is empty" << std::endl;
}
std::cout << "Size of deque: " << dq.size() << std::endl;
dq.clear(); // 清空 deque
3. 示例代码
以下是一个完整的示例代码,展示如何使用 std::deque
:
#include <iostream>
#include <deque>int main() {std::deque<int> dq = {1, 2, 3, 4, 5};// 插入操作dq.push_back(6); // 尾部插入 6dq.push_front(0); // 头部插入 0dq.insert(dq.begin() + 2, 99); // 在索引 2 的位置插入 99// 遍历 dequefor (int value : dq) {std::cout << value << " ";}std::cout << std::endl;// 删除操作dq.pop_back(); // 删除尾部元素dq.pop_front(); // 删除头部元素dq.erase(dq.begin() + 2); // 删除索引 2 的元素// 再次遍历 dequefor (int value : dq) {std::cout << value << " ";}std::cout << std::endl;// 访问元素std::cout << "Front element: " << dq.front() << std::endl; // 输出头部元素std::cout << "Back element: " << dq.back() << std::endl; // 输出尾部元素std::cout << "Element at index 2: " << dq[2] << std::endl; // 输出索引为 2 的元素// 检查是否为空if (dq.empty()) {std::cout << "Deque is empty" << std::endl;} else {std::cout << "Deque is not empty" << std::endl;}// 清空 dequedq.clear();if (dq.empty()) {std::cout << "Deque is now empty" << std::endl;}return 0;
}
4. 总结
std::deque
:一个双端队列,支持在两端高效地插入和删除元素。- 随机访问:支持通过索引快速访问元素。
- 动态大小:大小可以动态变化,类似于
std::vector
。 - 适用场景:适用于需要在两端频繁插入和删除元素的场景,如队列、栈等。