当前位置: 首页 > news >正文

C++ 中栈 (Stack) 详解和常见面试示例汇总实现

1. 栈的基本概念

  • 定义:栈(Stack)是一种 先进后出(LIFO, Last In First Out) 的数据结构。

  • 特点

    • 只能在一端(栈顶 Top)进行插入(Push)和删除(Pop)操作。
    • 操作受限,逻辑简单。
  • 常见操作

    • push(x):将元素压入栈顶
    • pop():弹出栈顶元素
    • top() / peek():获取栈顶元素(不删除)
    • empty():判断栈是否为空
    • size():获取栈中元素个数

2. 栈的底层实现

在 C++ 中,栈没有单独的底层结构,而是依赖 容器适配器 (Container Adapter) 实现。

  • 常见底层容器

    • deque(默认):双端队列,支持快速的首尾插入删除。
    • vector:连续存储,适合仅栈顶操作的场景。
    • list:双向链表。

源码:

template <class T, class Container = deque<T>>
class stack {
protected:Container c;  // 底层容器
public:bool empty() const { return c.empty(); }size_t size() const { return c.size(); }T& top() { return c.back(); }void push(const T& val) { c.push_back(val); }void pop() { c.pop_back(); }
};

这说明 stack 本质上是对底层容器的封装,限制了只能 后进先出


3. C++ STL 中的 stack 用法

需要头文件:

#include <stack>
#include <iostream>
using namespace std;

常用接口

stack<int> s;// 压栈
s.push(10);
s.push(20);// 访问栈顶
cout << s.top() << endl; // 20// 弹栈
s.pop();  // 删除 20
cout << s.top() << endl; // 10// 判断是否为空
if (!s.empty()) cout << s.size() << endl; // 1

4. 栈的常见应用

(1) 括号匹配

bool isValid(string s) {stack<char> st;for (char c : s) {if (c == '(') st.push(')');else if (c == '[') st.push(']');else if (c == '{') st.push('}');else if (st.empty() || st.top() != c) return false;else st.pop();}return st.empty();
}

(2) 表达式求值(后缀表达式)

int evalRPN(vector<string>& tokens) {stack<int> st;for (string& t : tokens) {if (t == "+" || t == "-" || t == "*" || t == "/") {int b = st.top(); st.pop();int a = st.top(); st.pop();if (t == "+") st.push(a + b);else if (t == "-") st.push(a - b);else if (t == "*") st.push(a * b);else st.push(a / b);} else {st.push(stoi(t));}}return st.top();
}

(3) 单调栈(求最近更大/更小元素)

vector<int> nextGreaterElement(vector<int>& nums) {vector<int> res(nums.size(), -1);stack<int> st;for (int i = 0; i < nums.size(); i++) {while (!st.empty() && nums[st.top()] < nums[i]) {res[st.top()] = nums[i];st.pop();}st.push(i);}return res;
}

5. 自己实现一个栈

基于 动态数组

template <typename T>
class MyStack {
private:vector<T> data;
public:void push(T val) { data.push_back(val); }void pop() { if (!empty()) data.pop_back(); }T top() { return data.back(); }bool empty() { return data.empty(); }size_t size() { return data.size(); }
};

基于 链表

template <typename T>
class Node {
public:T val;Node* next;Node(T v) : val(v), next(nullptr) {}
};template <typename T>
class LinkedStack {
private:Node<T>* head = nullptr;
public:void push(T val) {Node<T>* node = new Node<T>(val);node->next = head;head = node;}void pop() {if (head) {Node<T>* tmp = head;head = head->next;delete tmp;}}T top() { return head->val; }bool empty() { return head == nullptr; }
};

6. 栈的优缺点

优点:

  • 操作简单,效率高
  • 应用广泛:括号匹配、递归、表达式求值

缺点:

  • 功能有限,只能操作栈顶
  • 容量有限制(系统调用栈有栈溢出风险)

7. 与其他容器对比

数据结构插入删除位置访问时间适用场景
栈 stack仅栈顶O(1)LIFO 算法
队列 queue队尾入队,队首出队O(1)FIFO 算法
双端队列 deque两端均可O(1)双端操作
向量 vector任意位置O(1) 随机访问动态数组

8. 常见面试题-实现示例汇总

1. 括号匹配(LeetCode 20: Valid Parentheses)

思路

  • 遍历字符串,遇到左括号压栈,遇到右括号检查是否匹配栈顶。
  • 最后栈必须为空。
bool isValid(string s) {stack<char> st;for (char c : s) {if (c == '(') st.push(')');else if (c == '[') st.push(']');else if (c == '{') st.push('}');else if (st.empty() || st.top() != c) return false;else st.pop();}return st.empty();
}

2. 最小栈(LeetCode 155: Min Stack)

思路

  • 用两个栈:一个正常存值,一个维护最小值。
class MinStack {stack<int> st, minSt;
public:void push(int val) {st.push(val);if (minSt.empty() || val <= minSt.top()) minSt.push(val);}void pop() {if (st.top() == minSt.top()) minSt.pop();st.pop();}int top() { return st.top(); }int getMin() { return minSt.top(); }
};

3. 用栈实现队列(LeetCode 232: Implement Queue using Stacks)

思路

  • 用两个栈:一个负责入队,一个负责出队。
  • 出队时如果出栈为空,就把入栈的元素全部倒过去。
class MyQueue {stack<int> in, out;
public:void push(int x) { in.push(x); }int pop() {peek();int x = out.top(); out.pop();return x;}int peek() {if (out.empty()) {while (!in.empty()) {out.push(in.top());in.pop();}}return out.top();}bool empty() { return in.empty() && out.empty(); }
};

4. 用队列实现栈(LeetCode 225: Implement Stack using Queues)

思路

  • 用一个队列,每次 push 后把前面的元素重新入队到队尾,从而保持栈顶在队首。
class MyStack {queue<int> q;
public:void push(int x) {q.push(x);for (int i = 0; i < q.size() - 1; i++) {q.push(q.front());q.pop();}}int pop() {int x = q.front(); q.pop();return x;}int top() { return q.front(); }bool empty() { return q.empty(); }
};

5. 逆波兰表达式求值(LeetCode 150: Evaluate Reverse Polish Notation)

思路

  • 遇到数字就压栈,遇到运算符就弹出两个数运算后再压栈。
int evalRPN(vector<string>& tokens) {stack<int> st;for (string& t : tokens) {if (t == "+" || t == "-" || t == "*" || t == "/") {int b = st.top(); st.pop();int a = st.top(); st.pop();if (t == "+") st.push(a + b);else if (t == "-") st.push(a - b);else if (t == "*") st.push(a * b);else st.push(a / b);} else {st.push(stoi(t));}}return st.top();
}

6. 柱状图最大矩形(LeetCode 84: Largest Rectangle in Histogram)

思路

  • 单调栈维护递增高度索引,遇到下降时计算面积。
int largestRectangleArea(vector<int>& heights) {stack<int> st;heights.push_back(0); // 哨兵,保证清空栈int n = heights.size(), res = 0;for (int i = 0; i < n; i++) {while (!st.empty() && heights[st.top()] > heights[i]) {int h = heights[st.top()]; st.pop();int l = st.empty() ? -1 : st.top();res = max(res, h * (i - l - 1));}st.push(i);}return res;
}

7. 下一个更大元素(LeetCode 496: Next Greater Element I)

思路

  • 单调栈,维护递减栈,遇到更大元素时更新映射。
vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {unordered_map<int,int> mp;stack<int> st;for (int x : nums2) {while (!st.empty() && st.top() < x) {mp[st.top()] = x;st.pop();}st.push(x);}vector<int> res;for (int x : nums1) res.push_back(mp.count(x) ? mp[x] : -1);return res;
}

小结

这些题展示了 栈的典型应用场景

  • 括号匹配 → 符号配对
  • 最小栈 → 辅助栈维护状态
  • 栈 ↔ 队列 → 数据结构模拟
  • 逆波兰表达式 → 表达式计算
  • 柱状图最大矩形 → 单调栈区间计算
  • 下一个更大元素 → 单调栈找最近元素


文章转载自:

http://0FuYgRkl.nrbqf.cn
http://FHqINv3Y.nrbqf.cn
http://GvpKbMxJ.nrbqf.cn
http://4WfA4e6F.nrbqf.cn
http://OMzoUcg2.nrbqf.cn
http://nL8CHMcm.nrbqf.cn
http://clmMj8Ic.nrbqf.cn
http://WynasKWB.nrbqf.cn
http://9pFEaxfp.nrbqf.cn
http://Lztd3HpR.nrbqf.cn
http://D4XuSUri.nrbqf.cn
http://BZhosG22.nrbqf.cn
http://ixblrbI0.nrbqf.cn
http://FyUt1Tq7.nrbqf.cn
http://atnLb36j.nrbqf.cn
http://feugyyvO.nrbqf.cn
http://7AgAzH4M.nrbqf.cn
http://XL89HrVm.nrbqf.cn
http://URk4aHsY.nrbqf.cn
http://cfzgpXHQ.nrbqf.cn
http://300fjHoP.nrbqf.cn
http://6Jew3V67.nrbqf.cn
http://ngKfu6WV.nrbqf.cn
http://npd2cGOh.nrbqf.cn
http://Nw6gIvl9.nrbqf.cn
http://G22YyeJg.nrbqf.cn
http://Z21LlrO2.nrbqf.cn
http://3uJ8PwVt.nrbqf.cn
http://qM4a9y9Z.nrbqf.cn
http://Yj808edm.nrbqf.cn
http://www.dtcms.com/a/372097.html

相关文章:

  • [光学原理与应用-461]:波动光学 - 波片实现偏振态的转换或调整
  • 苍穹外卖Day12 | Apache POI、导出Excel报表、HttpServletResponse、工作台
  • 《Go小技巧易错点100例》第三十八篇
  • Conda 包管理器与环境管理使用指南
  • 笔记本、平板如何成为电脑拓展屏?向日葵16成为副屏功能一键实现
  • OpenHarmony 显示能效管理组件:掌控屏幕亮灭与亮度的核心利器
  • SQLite的基本操作
  • 第五课 C#语言基本元素概览,初始类型,变量与方法,算法简介
  • 【系统分析师】第12章-关键技术:软件架构设计(核心总结)
  • Lightdash:一个免费开源的自助式BI平台
  • Claude Code 使用教程
  • UML(统一建模语言)
  • Android开发-常用布局
  • Spring Cloud Gateway 进行集群化部署
  • EmbodiedOneVision——类似π0.5集成了离散自回归解码与连续流匹配去噪:单个模型中完成具身推理、动作生成
  • Paper reading - 03. Speech sequencing in the human precentral gyrus
  • Spring事务失效的常见陷阱与解决方案
  • 现代C++:现代C++?
  • ZSet
  • Linux初级篇
  • MySQL集群高可用架构——组复制 (MGR)
  • MySQL Cluster核心优缺点
  • RestTemplate使用 | RestTemplate设置http连接池参数
  • 01OpenCV简介
  • 美股市场股票数据API对接文档
  • Coze源码分析-资源库-删除插件-前端源码-核心接口与工具
  • 【深度学习】重采样(Resampling)
  • http接口幂等性
  • 无重复字符的最长子串
  • 架构思维:架构师视角的 FullGC 治理