深入解析STL中的stack、queue与priority_queue

引言

在前面 STL 系列中,我们学习了 vectordequelistsetmap 等容器。今天要讲的 queuestack 不是独立的容器,而是容器适配器 ------它们底层使用其他容器(默认是 deque),但只暴露特定的接口。

  • stack:后进先出(LIFO),只能操作栈顶

  • queue:先进先出(FIFO),只能操作队头和队尾

这种"限制接口"的设计正是适配器模式的核心思想:把功能丰富的容器包装成特定用途的数据结构,让使用者更安全、更语义化。

第一部分:stack(栈)

一、基本概念

栈是后进先出(LIFO,Last In First Out)的数据结构。最后放进去的元素,最先取出来。就像一摞盘子------最上面的先用。

二、创建与初始化

cpp 复制代码
#include <iostream>
#include <stack>
#include <vector>
#include <list>
using namespace std;

int main() {
    // 1. 默认(底层 deque)
    stack<int> s1;
    
    // 2. 指定底层容器为 vector
    stack<int, vector<int>> s2;
    
    // 3. 指定底层容器为 list
    stack<int, list<int>> s3;
    
    // 注意:stack 不支持初始化列表!
    // stack<int> s = {1,2,3};  // 错误!
    
    return 0;
}

三、核心操作

cpp 复制代码
stack<int> s;

// push:入栈
s.push(10);
s.push(20);
s.push(30);

// top:获取栈顶元素(不删除)
cout << s.top() << endl;  // 30

// pop:弹出栈顶元素(不返回)
s.pop();
cout << s.top() << endl;  // 20

// size / empty
cout << "元素个数:" << s.size() << endl;  // 2
cout << "是否为空:" << s.empty() << endl;  // 0(false)
操作 方法 说明
入栈 push(val) 将元素放入栈顶
出栈 pop() 移除栈顶元素,不返回值
获取栈顶 top() 返回栈顶元素的引用
大小 size() 返回元素个数
判空 empty() 是否为空

重要pop() 不返回被删除的值 !需要先 top() 获取值,再 pop() 删除。

cpp 复制代码
// ✅ 正确做法
int val = s.top();
s.pop();

// ❌ pop() 没有返回值
// int val = s.pop();  // 编译错误

四、完整示例

cpp 复制代码
#include <iostream>
#include <stack>
using namespace std;

int main() {
    stack<int> s;
    
    cout << "入栈顺序:";
    for (int i = 1; i <= 5; i++) {
        cout << i << " ";
        s.push(i);
    }
    cout << endl;
    
    cout << "出栈顺序:";
    while (!s.empty()) {
        cout << s.top() << " ";
        s.pop();
    }
    cout << endl;
    // 输出:5 4 3 2 1(后进先出)
    
    return 0;
}

第二部分:queue(队列)

一、基本概念

队列是先进先出(FIFO,First In First Out)的数据结构。先放进去的元素,先取出来。就像排队买票------先来的先服务。

二、创建与初始化

cpp 复制代码
#include <iostream>
#include <queue>
#include <list>
using namespace std;

int main() {
    // 1. 默认(底层 deque)
    queue<int> q1;
    
    // 2. 指定底层容器为 list
    queue<int, list<int>> q2;
    
    // 错误!vector 没有 pop_front
    // queue<int, vector<int>> q3;  // 编译错误!
    
    return 0;
}

三、核心操作

cpp 复制代码
queue<int> q;

// push:入队(队尾)
q.push(10);
q.push(20);
q.push(30);

// front:获取队头元素(不删除)
cout << q.front() << endl;  // 10

// back:获取队尾元素(不删除)
cout << q.back() << endl;   // 30

// pop:出队(队头)
q.pop();
cout << q.front() << endl;  // 20

// size / empty
cout << "元素个数:" << q.size() << endl;  // 2
操作 方法 说明
入队 push(val) 将元素放入队尾
出队 pop() 移除队头元素,不返回值
获取队头 front() 返回队头元素的引用
获取队尾 back() 返回队尾元素的引用
大小 size() 返回元素个数
判空 empty() 是否为空

四、完整示例

cpp 复制代码
#include <iostream>
#include <queue>
using namespace std;

int main() {
    queue<int> q;
    
    cout << "入队顺序:";
    for (int i = 1; i <= 5; i++) {
        cout << i << " ";
        q.push(i);
    }
    cout << endl;
    
    cout << "出队顺序:";
    while (!q.empty()) {
        cout << q.front() << " ";
        q.pop();
    }
    cout << endl;
    // 输出:1 2 3 4 5(先进先出)
    
    return 0;
}

第三部分:stack vs queue 对比

操作 stack queue
插入 push() 栈顶 push() 队尾
删除 pop() 栈顶 pop() 队头
获取 top() 栈顶 front() 队头 / back() 队尾
特点 后进先出(LIFO) 先进先出(FIFO)
类比 一摞盘子 排队买票
默认底层 deque deque
可用底层 deque / vector / list deque / list(不能用 vector)

第四部分:priority_queue(优先队列)

一、基本概念

priority_queue 是另一种队列适配器,它不按入队顺序出队 ,而是按优先级------默认最大的元素优先出队。

二、基本操作

cpp 复制代码
#include <iostream>
#include <queue>
#include <functional>  // greater<>
using namespace std;

int main() {
    // 默认大顶堆(降序出队)
    priority_queue<int> pq1;
    pq1.push(3);
    pq1.push(5);
    pq1.push(1);
    pq1.push(9);
    
    cout << "大顶堆出队:";
    while (!pq1.empty()) {
        cout << pq1.top() << " ";  // 9 5 3 1
        pq1.pop();
    }
    cout << endl;
    
    // 小顶堆(升序出队)
    priority_queue<int, vector<int>, greater<int>> pq2;
    pq2.push(3);
    pq2.push(5);
    pq2.push(1);
    pq2.push(9);
    
    cout << "小顶堆出队:";
    while (!pq2.empty()) {
        cout << pq2.top() << " ";  // 1 3 5 9
        pq2.pop();
    }
    cout << endl;
    
    return 0;
}
操作 方法 说明
入队 push(val) 插入并自动调整
出队 pop() 移除堆顶元素
获取堆顶 top() 返回优先级最高的元素
大小 size() 元素个数
判空 empty() 是否为空

三、自定义优先级

cpp 复制代码
// 自定义类型
struct Student {
    string name;
    int score;
};

// 自定义比较器(分数高的优先)
struct CompareScore {
    bool operator()(const Student& a, const Student& b) {
        return a.score < b.score;  // 大顶堆:分数高的优先
    }
};

int main() {
    priority_queue<Student, vector<Student>, CompareScore> pq;
    pq.push({"张三", 85});
    pq.push({"李四", 92});
    pq.push({"王五", 78});
    
    while (!pq.empty()) {
        cout << pq.top().name << ": " << pq.top().score << endl;
        pq.pop();
    }
    // 李四: 92
    // 张三: 85
    // 王五: 78
    
    return 0;
}

第五部分:适配器底层容器选择

适配器 默认容器 可选容器 不能用 原因
stack deque vector, list --- 都需要 back/push_back/pop_back
queue deque list vector vector 没有 pop_front
priority_queue vector deque list 需要随机访问

总结

一、核心操作速查

操作 stack queue priority_queue
插入 push push push
删除 pop pop pop
访问 top() front() / back() top()
特点 LIFO FIFO 按优先级

二、适配器设计思想

三、一句话记忆

stack 后进先出只操作栈顶(push/pop/top),queue 先进先出操作两端(push/pop/front/back),priority_queue 按优先级出队(push/pop/top)。三者都是容器适配器,默认底层用 deque,只暴露有限接口。

相关推荐
彦为君1 小时前
JavaSE-07-异常机制
java·开发语言·后端·python·spring
OxyTheCrack1 小时前
【Golang】简述make与new内置函数以及两者的区别
开发语言·golang
Rain5092 小时前
mini-cc 的 MCP 协议:给 AI 装个 USB-C 接口
c语言·开发语言·前端·人工智能·架构·node.js·ai编程
华科大胡子2 小时前
AI开发者的网络卡点:Anthropic连接超时
开发语言·php
磊 子2 小时前
STL无序关联容器—unorded_set+unorded_map
开发语言·c++
初夏睡觉2 小时前
数据结构学习之~二叉堆 (P3378 【模版】堆)
数据结构·c++·学习
AI人工智能+电脑小能手3 小时前
【大白话说Java面试题 第84题】【Mysql篇】第14题:为什么用 InnoDB 存储引擎的表建议用整型的自增主键?
java·开发语言·数据库·mysql·面试
云泽8083 小时前
笔试算法 - 链表篇(一):移除、反转、合并、回文判断全解析
数据结构·c++·算法·链表
小poop3 小时前
深入理解指针(中):数组与指针的进阶之旅
c++