【C++指南】STL stack 完全解读(一):从入门到掌握基础操作

【C++指南】STL stack 完全解读(一):从入门到掌握基础操作
.💓 博客主页:倔强的石头的ZEEKLOG主页
📝Gitee主页:倔强的石头的gitee主页
⏩ 文章专栏:《C++指南》
期待您的关注

文章目录

引言

作为线性数据结构的经典代表,栈(stack)以其独特的后进先出(LIFO)特性,在函数调用、表达式求值、括号匹配等场景中扮演着关键角色。

在这里插入图片描述


在这里插入图片描述

本文将深入解析C++ STL中的stack容器适配器,通过理论讲解与实战代码演示,帮助读者掌握这一重要工具的使用精髓。
本篇不仅适合初窥门径的新手,也能为经验丰富的开发者提供新的视角。

关于栈的结构的详细介绍,可以参考我之前写的一篇用C语言手搓栈的讲解文章
👇
【数据结构与算法】使用数组实现栈:原理、步骤与应用

一、C++ STL stack全景解析

1.1 容器适配器的本质

stack并非独立的容器,而是构建于其他序列容器之上的容器适配器。默认情况下,它使用deque作为底层容器,这种设计使其具有以下显著特点:

template<classT,classContainer= deque<T>>classstack;
  • 访问约束性:仅允许通过栈顶(top)进行元素操作
  • 操作高效性:所有操作的时间复杂度均为O(1)
  • 容器可置换性:支持替换底层容器为vectorlist

1.2 核心价值剖析

  1. 接口简洁性:通过有限的接口规范操作,避免误用
  2. 类型安全性:模板机制保证元素类型统一
  3. 内存安全性:自动管理内存生命周期
  4. 算法适配性:天然适合需要LIFO特性的算法场景

二、stack核心操作深度解读

2.1 基础操作矩阵

操作语法时间复杂度说明
压栈push(const T& val)O(1)添加元素到栈顶
弹栈pop()O(1)移除栈顶元素
访问栈顶top()O(1)返回栈顶元素的引用
判空检测empty()O(1)判断栈是否为空
容量查询size()O(1)返回当前元素数量

2.2 实战代码演练

示例1:基础操作全流程
#include<iostream>#include<stack>intmain(){ std::stack<int> s;// 压栈操作 s.push(10);// 栈底 -> [10] s.push(20);// [10, 20] s.push(30);// 栈顶 -> [10, 20, 30]// 访问栈顶 std::cout <<"Top element: "<< s.top()<< std::endl;// 输出30// 弹栈操作 s.pop();// 移除30 s.pop();// 移除20// 判空检测if(!s.empty()){ std::cout <<"Stack size: "<< s.size()<< std::endl;// 输出1}return0;}
示例2:经典括号匹配算法
boolisBalanced(const std::string& expr){ std::stack<char> s; std::unordered_map<char,char> mapping ={{')','('},{']','['},{'}','{'}};for(char ch : expr){if(mapping.count(ch)){if(s.empty()|| s.top()!= mapping[ch])returnfalse; s.pop();}else{ s.push(ch);}}return s.empty();}// 测试用例 std::cout << std::boolalpha; std::cout <<isBalanced("({[]})")<< std::endl;// 输出true std::cout <<isBalanced("([)]")<< std::endl;// 输出false

三、进阶应用场景

3.1 表达式求值

栈在处理中缀表达式转后缀表达式(逆波兰表示法)时表现卓越:

std::string infixToPostfix(const std::string& infix){ std::stack<char> op_stack; std::string postfix;// ... 转换逻辑(运算符优先级处理)return postfix;}

关于逆波兰表达式的实践,单独写了一篇文章来讲解
【C++经典例题】逆波兰表达式求值:栈的经典应用与实现详解

3.2 函数调用栈

编译器使用调用栈管理函数调用关系:

voidfuncA(){funcB();// 压入调用栈}voidfuncB(){// 返回时自动弹栈}

3.3 算法优化

在深度优先搜索(DFS)中,栈可替代递归实现:

voiddfs(Node* root){ std::stack<Node*> s; s.push(root);while(!s.empty()){ Node* current = s.top(); s.pop();// 处理节点for(auto child : current->children){ s.push(child);}}}

结语

通过对STL stack的系统性学习,我们不仅掌握了其基本操作,更领略了其在算法设计中的精妙应用。然而,这仅仅是冰山一角——stack的真正魅力在于其精巧的底层实现。
在下一篇文章中,我们将揭开stack的神秘面纱,深入探讨其底层容器选择策略,并手把手指导实现自定义栈结构。届时,您将真正理解STL设计者的智慧结晶,并能够根据特定需求优化栈的实现。

下篇预告:《解剖STL stack:从底层实现到自定义栈设计》——深入STL源码,解析deque的适配机制,并实现支持动态扩容的安全栈结构。

Read more

【数据结构和算法】面试必刷之随机链表复制:这三步让你彻底吃透 random 指针

【数据结构和算法】面试必刷之随机链表复制:这三步让你彻底吃透 random 指针

🔥小龙报:个人主页 🎬作者简介:C++研发,嵌入式,机器人等方向学习者 ❄️个人专栏:《C语言》《【初阶】数据结构与算法》 ✨ 永远相信美好的事情即将发生 文章目录 * 前言 * 一、随即链表的复制 * 1.1 题目 * 1.2 算法原理 * 1.3 代码 * 总结与每日励志 前言 随机链表的复制是数据结构中的经典难题,核心难点在于复制节点的random指针——其指向的节点可能尚未创建,也可能指向链表中的任意节点。本文采用“原地拷贝+拆分”的最优思路,分三步拆解解题逻辑,结合代码实现与原理分析,清晰讲解如何高效解决该问题,帮助读者吃透random指针的处理技巧,掌握链表操作的核心思维。 一、随即链表的复制 1.1 题目 链接:随机链表的复制 1.2 算法原理

By Ne0inhk

2026牛客寒假算法基础集训营1

A(逆元 模拟 状态压缩  概率论  逆元) 大致题意: 有八个独立的数位显示器,每个显示器的每个二极管被点亮的概率为pi ,管与管之间互相独立,显示器 之间也相互独立,求分别显示出两个四位合法数字,且数字之和等于输入的常数 的概率。 现在请你计算出如下事件的概率(需全部满足): • 最终所有显示器均有灯管被点亮(也就是说显示器的灯管不能全灭)。 • 最终所有显示器显示的结果均为合法数字。 • 第一排的显示器前后拼接形成的十进制数记作A,第二排的显示器前后拼接形成的十进制数记作 B的话,满足:A+B=C。 (需要注意的是:我们认为A和B都可以存在前导0。) 也就是说 我们要让所有显示器亮出来一个合法数字并且前后数字之和为c  首先 显示器之间完全独立 我们可以算出每个显示器表示0-9的概率  这样的话我们就可以用独立的概率乘积算出某个数字的概率   这样我们就可以枚举1-2026 的所有数字 算出概率 然后算出所有组合的概率和 接下来我们要解决如何算出表示0-9的概率  这里需要用到状态压缩的技巧  我们在二进制中 将需要点亮的灯管定为1  不需要的定为0   我们

By Ne0inhk

Flutter 三方库 in_date_utils 的鸿蒙化适配指南 - 在鸿蒙系统上构建极致、高效的日期逻辑处理与万年历算法引擎

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 in_date_utils 的鸿蒙化适配指南 - 在鸿蒙系统上构建极致、高效的日期逻辑处理与万年历算法引擎 在鸿蒙(OpenHarmony)系统的日历、任务管理或考勤应用中,如何快速计算某月的天数、判断闰年、或优雅地对日期进行加减操作?in_date_utils 为开发者提供了一套开箱即用的日期增强工具集。本文将深入实战其在鸿蒙生态中的应用。 前言 什么是 in_date_utils?它是 Dart 原生 DateTime 的强力补丁。在 Flutter for OpenHarmony 的实际开发中,我们经常需要处理诸如“上周一的日期”、“本月最后一个周五”等复杂的业务逻辑。利用该库,我们可以避免重复编写琐碎的日期数学运算,让鸿蒙应用的代码更加简洁、易读且稳健。 一、

By Ne0inhk

优选算法——前缀和

👇作者其它专栏 《数据结构与算法》《算法》《C++起始之路》 前缀和相关题解 1.前缀和 算法思路: a.先预处理出来一个【前缀和】数组:         用dp[i]表示:[1,i]区间内所有元素的和,那么dp[i-1]里面存的就是[1,i-1]区间内所有元素的和,那么:可得到递推公式:dp[i]=dp[i-1]+arr[i]; b.使用前缀和数组,【快速】求出【某一个区间内】所有元素的和:         当访问的区间是[l,r]时:区间内所有元素的和为:dp[r]-dp[l-r]。 #include <

By Ne0inhk