CC++ & Algorithm

C++ STL queue 队列 —— 像排队买奶茶一样

中等23
语言版本:C++Python
概述:队列是一种“先进先出”的数据结构,先来的人先服务,后来的排后面。

排队买奶茶?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;
}

⚠️ 常见错误与注意事项

  1. 空队列时调用 front() 或 back()
    如果队列是空的,你却想看看队首是谁,程序会直接崩溃(运行时报错,或者得到垃圾值)。
    ✅ 正确做法:调用前先用 empty() 检查。

    queue<int> q;  // 空队列
    if (!q.empty()) {
        cout << q.front() << endl;  // 安全
    }
    
  2. pop() 之前忘记访问 front()
    pop() 只是删除队首,并不会返回它。如果你想拿到这个元素并删除,应该先保存再pop:

    int first = q.front();  // 保存
    q.pop();                // 删除
    
  3. 用 queue 做“循环排队”
    如果你想让队伍转圈(比如轮流做任务),队列本身不支持从队首取出后放回队尾。要手动实现:先 front()pop(),然后 push() 回到队尾。

  4. 类型搞错
    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 模拟“循环排队”(比如击鼓传花),应该怎么做?试试写一写代码。

例题精讲

1单选题

下列关于C++ STL queue(队列)的数据存取特性描述正确的是?

A先进先出(FIFO)
B先进后出(LIFO)
C后进先出(LIFO)
D随机存取
2判断题

调用queue的pop()成员函数后,会返回被删除的队首元素。

3填空题
以下代码使用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;
}
4单选题

C++ STL中的queue默认使用哪个容器作为底层实现?

Adeque
Bvector
Clist
Darray
5判断题

queue容器支持使用迭代器进行随机访问。