C++ STL queue 队列 —— 像排队买奶茶一样
中等23排队买奶茶?Queue 队列就是干这个的!
放学后你和小伙伴去奶茶店,大家很自觉排成一队:先来的人站在最前面,买到奶茶先走,新来的只能排在队尾。C++里的queue(队列)就是模拟这种规则的数据结构。它只有两个口:一个口用来加入新人(队尾),另一个口用来让最前面的人离开(队首)。你无法直接插队,也不能从中间拿走一个人。
这种“先进先出”(First In First Out,简称FIFO)的规则在计算机里到处都有:打印机任务排队、键盘输入缓冲、广度优先搜索(BFS)等等。只要记住“先进先出”四个字,就掌握了queue的精髓。
? 怎么使用queue?
首先,你需要包含头文件 #include <queue>。创建一个队列的格式是:queue<类型> 名字; 比如 queue<string> line; 表示一个存储字符串的队列,每个字符串代表一个人名。
常用操作(六兄弟):
push(值)—— 把元素放到队尾(排队)pop()—— 移除队首元素(排到的人离开队伍)front()—— 查看队首元素(看看排在最前面的是谁)back()—— 查看队尾元素(看看最后来的是谁)empty()—— 判断队列是否为空(返回 true 或 false)size()—— 返回队列中元素个数(当前有多少人)
小贴士:
front()和back()只是看一眼,不会把人赶走;pop()才是真正移除。想把元素取出来,通常先front()再pop()。
? 生活中的例子:食堂打饭、超市收银
想象一下食堂打饭:队伍最前面的同学打完饭就走,后面的同学往前挪。如果用队列来模拟:
#include <queue>
#include <string>
#include <iostream>
using namespace std;
int main() {
queue<string> lunch_line; // 打饭队列,存人名
lunch_line.push("李雷"); // 李雷先到
lunch_line.push("韩梅梅"); // 韩梅梅排第二
lunch_line.push("Jim"); // Jim 最后来
cout << "队首:" << lunch_line.front() << endl; // 输出:李雷
cout << "队尾:" << lunch_line.back() << endl; // 输出:Jim
// 开始打饭,每人取走
while (!lunch_line.empty()) {
cout << lunch_line.front() << " 打了饭,离开队伍" << endl;
lunch_line.pop(); // 移除队首
}
cout << "队列空了" << endl;
return 0;
}
⚠️ 常见错误与注意事项
-
空队列时调用 front() 或 back()
如果队列是空的,你却想看看队首是谁,程序会直接崩溃(运行时报错,或者得到垃圾值)。
✅ 正确做法:调用前先用empty()检查。queue<int> q; // 空队列 if (!q.empty()) { cout << q.front() << endl; // 安全 } -
pop() 之前忘记访问 front()
pop()只是删除队首,并不会返回它。如果你想拿到这个元素并删除,应该先保存再pop:int first = q.front(); // 保存 q.pop(); // 删除 -
用 queue 做“循环排队”
如果你想让队伍转圈(比如轮流做任务),队列本身不支持从队首取出后放回队尾。要手动实现:先front()再pop(),然后push()回到队尾。 -
类型搞错
queue<string>里面只能放字符串,不能放整数。如果需要放多种数据,可以考虑结构体。
? 完整示例:模拟 ATM 取号机
假设银行里有一个取号机,每来一个人就取一个号(号码递增),然后排队等待叫号。每次叫号,显示当前号码并移除。
#include <iostream>
#include <queue>
using namespace std;
int main() {
queue<int> ticket_queue; // 存储号码的队列
int current_number = 1; // 当前号码(从1开始)
// 来3个人取号
ticket_queue.push(current_number++); // 1号
ticket_queue.push(current_number++); // 2号
ticket_queue.push(current_number++); // 3号
cout << "当前排队人数:" << ticket_queue.size() << endl;
// 叫号服务
while (!ticket_queue.empty()) {
int now = ticket_queue.front(); // 查看队首号码
ticket_queue.pop(); // 移除该号码
cout << "请 " << now << " 号到窗口办理" << endl;
}
cout << "所有顾客办理完毕" << endl;
return 0;
}
运行结果:
当前排队人数:3
请 1 号到窗口办理
请 2 号到窗口办理
请 3 号到窗口办理
所有顾客办理完毕
? 相关知识点指引
- deque(双端队列):可以在两端插入和删除,queue 底层默认用 deque 实现,但 queue 限制了操作。
- priority_queue(优先队列):每次弹出优先级最高的元素(比如VIP插队),适合任务调度。
- stack(栈):先进后出,像一叠盘子,只能从顶部操作。
- list(双向链表):也能实现队列,但 queue 是对容器的封装,更简洁。
思考题:如果用
queue模拟“循环排队”(比如击鼓传花),应该怎么做?试试写一写代码。
例题精讲
下列关于C++ STL queue(队列)的数据存取特性描述正确的是?
调用queue的pop()成员函数后,会返回被删除的队首元素。
以下代码使用queue模拟奶茶店排队,请填空:
#include <queue>
using namespace std;
int main() {
queue<int> q;
q.push(1);
q.push(2);
q.push(3);
int first = q.___(); // 获取队首元素,但不出队
return 0;
}C++ STL中的queue默认使用哪个容器作为底层实现?
queue容器支持使用迭代器进行随机访问。