
🔥个人主页:胡萝卜3.0****
📖个人专栏:************************************************************************************************************************************************************************************************************************************************************《C语言》、《数据结构》 、《C++干货分享》、LeetCode&牛客代码强化刷题****************************************************************************************************************************************************************************************************************************************************************
⭐️人生格言:不试试怎么知道自己行不行
🎥胡萝卜3.0🌸的简介:


目录
[一. 先搞懂基础:Stack 与 Queue 的核心特性](#一. 先搞懂基础:Stack 与 Queue 的核心特性)
[2.1 核心特性:](#2.1 核心特性:)
[2.2 stack核心接口使用](#2.2 stack核心接口使用)
[2.2.1 创建stack对象](#2.2.1 创建stack对象)
[2.2.2 常用接口](#2.2.2 常用接口)
[3.1 核心特性:](#3.1 核心特性:)
[3.2 核心接口使用](#3.2 核心接口使用)
[3.2.1 创建queue对象](#3.2.1 创建queue对象)
[3.2.2 常用接口](#3.2.2 常用接口)
[4.1 最小栈](#4.1 最小栈)
[4.2 栈的压入、弹出序列](#4.2 栈的压入、弹出序列)
[4.3 逆波兰表达式求值](#4.3 逆波兰表达式求值)
[4.4 二叉树的层序遍历](#4.4 二叉树的层序遍历)
一. 先搞懂基础:Stack 与 Queue 的核心特性
在写代码前,首先要明确两者的 "数据访问规则"------ 这是它们区别于其他容器的关键:
|-------|-------------|-----------------|
| 容器 | 核心规则 | 访问特性 |
| stack | 后进先出(LIFO) | 仅能访问"栈顶"元素 |
| queue | 先进先出( FIFO) | 仅能访问"队头"和"堆尾"元素 |
两者的共同特性是:不支持下标访问和迭代器
二、栈(Stack):受限的"单口管道"操作
2.1 核心特性:
- 访问规则:只能从"栈顶"添加或删除元素(最后入栈的元素最先出栈)
- 适用场景:函数调用栈,表达式求值等。

2.2 stack核心接口使用
2.2.1 创建stack对象
这里就很直接上代码演示~~
cpp
#include<iostream>
#include<stack>
#include<vector>
#include<list>
using namespace std;
void testStack1()
{
//定义栈:默认存储int类型,底层依赖deque实现
stack<int> st1;
//可指定底层容器(如vector、list)
stack<int, vector<int>> st2;
stack<int, list<int>> st2;
}
stack 是一个容器适配器,我们可以根据需求选择最合适的底层容器。
-
选择
std::vector:可能获得更好的缓存局部性,但动态扩展时可能需要重新分配内存。 -
选择
std::deque(默认):首尾插入删除效率都高,不需要大量的内存重新分配。 -
选择
std::list:在中间插入删除效率高(虽然栈用不到),但内存开销稍大。
2.2.2 常用接口
|---------|----------------|
| 函数说明 | 接口说明 |
| stack() | 构造空的栈 |
| push() | 将元素val压入stack中 |
| pop() | 出栈操作 |
| top() | 返回栈顶元素的引用 |
| empty() | 检测stack是否为空 |
| size() | 返回stack中元素的个数 |
这些接口的使用很简单,我们快速演示一下:
- stack()
创建一个空的栈
cpp
void testStack1()
{
//定义栈:默认存储int类型,底层依赖deque实现
stack<int> st1;
//可指定底层容器(如vector、list)
stack<int, vector<int>> st2;
stack<int, list<int>> st3;
}
- push()
将数据压入栈中
cpp
void testStack1()
{
stack<int> st1;
//压栈
st1.push(1);
st1.push(2);
st1.push(3);
st1.push(4);
st1.push(5);
}
- top()
取栈顶元素
cpp
void testStack1()
{
stack<int> st1;
//压栈
st1.push(1);
st1.push(2);
st1.push(3);
st1.push(4);
st1.push(5);
//取栈顶元素
int ret = st1.top();
cout << ret << endl;
}
- pop()
出栈
cpp
void testStack1()
{
stack<int> st1;
//压栈
st1.push(1);
st1.push(2);
st1.push(3);
st1.push(4);
st1.push(5);
//取栈顶元素
int ret = st1.top();
cout << ret << endl;//打印结果:5
//出栈
st1.pop();
//取栈顶元素
ret = st1.top();//打印结果:4
cout << ret << endl;
}
- size()
求出栈中的有效数据个数
cpp
void testStack1()
{
stack<int> st1;
//压栈
st1.push(1);
st1.push(2);
st1.push(3);
st1.push(4);
st1.push(5);
//求出有效数据个数
size_t _size = st1.size();
cout << _size << endl;
}
- empty()
判断栈是否为空,栈为空返回true,栈不为空返回false
cpp
void testStack1()
{
stack<int> st1;
//压栈
st1.push(1);
st1.push(2);
st1.push(3);
st1.push(4);
st1.push(5);
//判断栈是否为空
bool ret = st1.empty();
cout << ret << endl;//输出结果为0,说明栈不为空
}
三、队列(Queue):先进先出的公平性规则
3.1 核心特性:
- 访问规则:从"队尾"添加元素,从"队头"删除元素(最先入队的元素最先出队)
- 适用场景:任务调度(如打印队列)、消息队列、广度优先搜索(BFS)等

3.2 核心接口使用
3.2.1 创建queue对象
cpp
void testQueue1()
{
//定义队列:默认底层依赖deque实现
queue<int> q;
//可指定底层容器(如list,不能使用vector,std::vector 不支持 pop_front() 操作)
queue<int, list<int>> q2;
}
3.2.2 常用接口
|---------|----------------------------|
| 函数声明 | 接口说明 |
| empty() | 检测队列是否为空,是返回true,否则返回false |
| size() | 返回队列中有效元素的个数 |
| front() | 返回队头元素的引用 |
| back() | 返回队尾元素的引用 |
| push() | 在队尾将元素val入队列 |
| pop() | 将队头元素出队列 |
- push()
从队尾入队列
cpp
void testQueue1()
{
queue<int> q;
//入队
q.push(1);
q.push(2);
q.push(3);
q.push(4);
q.push(5);
while (!q.empty())
{
cout << q.front() << " ";
q.pop();
}
}
- pop()
从队头出数据
cpp
void testQueue1()
{
queue<int> q;
//入队
q.push(1);
q.push(2);
q.push(3);
q.push(4);
q.push(5);
//出队
q.pop();
}
- front()
返回队头元素的引用
cpp
void testQueue1()
{
queue<int> q;
//入队
q.push(1);
q.push(2);
q.push(3);
q.push(4);
q.push(5);
//返回队头元素的引用
int _front = q.front();
cout << _front << endl;
}
- back()
返回队尾元素的引用
cpp
void testQueue1()
{
queue<int> q;
//入队
q.push(1);
q.push(2);
q.push(3);
q.push(4);
q.push(5);
//返回队尾元素的引用
int _back = q.back();
cout << _back << endl;
}
- size()
求出有效数据个数
cpp
void testQueue1()
{
queue<int> q;
//入队
q.push(1);
q.push(2);
q.push(3);
q.push(4);
q.push(5);
//有效数据个数
size_t _size = q.size();
cout << _size << endl;
}
- empty()
判断队列是否为空
cpp
void testQueue1()
{
queue<int> q;
//入队
q.push(1);
q.push(2);
q.push(3);
q.push(4);
q.push(5);
//判断队列是否为空
bool ret = q.empty();
cout << ret << endl;
}
ok,stack和queue的使用就说到这里,接下来我们来做几个题
四、实战训练题
4.1 最小栈
题目链接:
- 题目描述:

- 解题思路:

- 代码演示:
cpp
class MinStack {
public:
//这里的构造不用写,默认生成的构造会去调用stack中的构造
MinStack() {
}
void push(int val) {
_str.push(val);
if(_minstr.empty()||_str.top()<=_minstr.top())
{
_minstr.push(val);
}
}
void pop() {
if(_str.top()==_minstr.top())
{
_minstr.pop();
}
_str.pop();
}
int top() {
return _str.top();
}
int getMin() {
return _minstr.top();
}
private:
stack<int> _str;
stack<int> _minstr;
};
4.2 栈的压入、弹出序列
题目链接:
- 题目描述:

简单来说:就是判断出栈顺序是否和提供的出栈顺序是相同的,相同返回true,不相同返回false
- 解题思路:

- 代码演示:
cpp
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param pushV int整型vector
* @param popV int整型vector
* @return bool布尔型
*/
bool IsPopOrder(vector<int>& pushV, vector<int>& popV) {
size_t posh=0,posp=0;
stack<int> st;
while(posh < pushV.size())
{
st.push(pushV[posh]);
while(!st.empty()&&st.top()==popV[posp])
{
st.pop();
posp++;
}
//跳出循环,说明不相等了,继续入栈
posh++;
}
return st.empty();
}
};
4.3 逆波兰表达式求值
题目链接:
- 题目描述:


- 解题思路:

- 代码演示:
cpp
class Solution {
public:
int evalRPN(vector<string>& tokens) {
stack<int> st;
for(auto& e:tokens)
{
if(e=="+"||e=="-"||e=="*"||e=="/")
{
//操作符,进行运算操作
int right=st.top();
st.pop();
int left=st.top();
st.pop();
switch(e[0])
{
case '+':
st.push(left+right);
break;
case '-':
st.push(left-right);
break;
case '*':
st.push(left*right);
break;
case '/':
st.push(left/right);
break;
}
}
else
{
//操作数
//stoi:将整型字符转成整型int
st.push(stoi(e));
}
}
return st.top();
}
};
4.4 二叉树的层序遍历
题目链接:
- 题目描述:

- 解题思路:
每次只出当前层的元素,出之前把它的左右孩子插入栈中,等到当前层的出完出去之后更新levelSize,此时刚好等于现在栈中的元素个数。

- 代码演示:
cpp
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
queue<TreeNode*> q;
size_t levelSize;
if(root)
{
q.push(root);
levelSize=1;
}
vector<vector<int>> vv;
//一层一层的出
while(!q.empty())
{
vector<int> v;
//一层一层的出
while(levelSize--)
{
TreeNode* _front=q.front();
v.push_back(_front->val);
//让不为空的左右孩子入队列
q.pop();
if(_front->left)
{
q.push(_front->left);
}
if(_front->right)
{
q.push(_front->right);
}
}
vv.push_back(v);
levelSize=q.size();
}
return vv;
}
};