1. stack<T> s; ------ 定义栈对象
作用
创建一个空的、存储 T 类型元素的栈对象,STL 会自动管理栈的内存(无需手动分配 / 释放)。
示例
#include <stack>
using namespace std;
// 定义存储字符的栈
stack<char> s1;
// 定义存储整数的栈
stack<int> s2;
// 定义存储字符串的栈
stack<string> s3;
2. s.push(val); ------ 入栈(压入元素)
作用
把 val 这个元素添加到栈的最顶端,栈的大小会自动 +1,底层由 STL 自动扩容(无需担心空间不足)。
示例
stack<int> s;
// 压入整数 10(类型匹配)
s.push(10);
// 压入整数 20,此时栈顶是 20
s.push(20);
// 错误示例:栈是 int 类型,不能压入字符串
// s.push("abc");
3. s.pop(); ------ 出栈(移除栈顶元素)
作用
仅移除栈顶的元素 ,但不会返回该元素(这是新手最容易踩的坑),栈的大小会自动 -1。
关键注意点
- 不能对空栈 调用
pop(),否则会触发程序崩溃(未定义行为); - 若需要获取栈顶元素,必须先调用
s.top()取值,再调用s.pop()删除。
示例
stack<int> s;
s.push(10);
s.push(20);
// 先取栈顶元素(20),再移除
int topVal = s.top();
s.pop(); // 此时栈里只剩 10
// 错误示例:空栈调用 pop()
// s.pop();
// s.pop();
4. s.top(); ------ 获取栈顶元素
作用
返回栈顶元素的引用 (可以读取,也可以修改),但不会移除该元素,栈的大小不变。
关键注意点
- 不能对空栈 调用
top(),否则程序崩溃; - 返回的是引用,若修改该值,栈内的元素也会被修改(按需使用)。
示例
stack<int> s;
s.push(10);
s.push(20);
// 读取栈顶元素:输出 20
cout << s.top() << endl;
// 修改栈顶元素(引用特性)
s.top() = 99;
// 再次读取:输出 99
cout << s.top() << endl;
// 错误示例:空栈调用 top()
// stack<int> emptyStack;
// cout << emptyStack.top() << endl;
5. s.empty(); ------ 判断栈是否为空
作用
返回一个 bool 类型的值:
true:栈为空(没有任何元素);false:栈不为空(有至少一个元素)。
核心用途
作为 pop()/top() 的前置检查,避免对空栈操作导致崩溃,是栈使用中最关键的边界检查。
示例
stack<int> s;
// 栈为空,输出 true
cout << boolalpha << s.empty() << endl;
s.push(10);
// 栈不为空,输出 false
cout << boolalpha << s.empty() << endl;
// 正确用法:先判空,再操作
if (!s.empty()) {
s.pop();
}
6. s.size(); ------ 获取栈的元素个数
写法拆解
| 部分 | 含义 |
|---|---|
s |
已定义的栈对象名; |
.size |
栈的成员函数,专门用于获取元素个数; |
() |
无参数; |
; |
语句结束符(通常赋值给变量或直接使用)。 |
作用
返回栈中元素的个数,返回类型是 size_t(无符号整数,可理解为非负整数),栈为空时返回 0。
补充
size() 也能做边界检查(比如 s.size() > 0 等价于 !s.empty()),但 empty() 更高效(无需计算元素个数,仅判断是否为空)。
示例
stack<int> s;
// 输出 0
cout << s.size() << endl;
s.push(10);
s.push(20);
// 输出 2
cout << s.size() << endl;
s.pop();
// 输出 1
cout << s.size() << endl;
总结
| 写法 | 核心作用 | 关键注意点 |
|---|---|---|
stack<T> s; |
定义存储 T 类型的空栈 | 必须指定类型 T,包含 <stack> 头文件 |
s.push(val); |
把 val 压入栈顶,栈大小 +1 | val 类型必须和 T 一致 |
s.pop(); |
移除栈顶元素,栈大小 -1 | 不返回元素,空栈调用会崩溃 |
s.top(); |
获取栈顶元素(引用),栈大小不变 | 空栈调用会崩溃,可修改栈内元素 |
s.empty(); |
判断栈是否为空,返回 bool 值 | 优先用于 pop()/top() 的前置检查 |
s.size(); |
获取栈的元素个数,返回 size_t 类型 | 可替代 empty() 但效率更低 |
核心使用逻辑:先判空(empty())→ 再取栈顶(top())→ 最后出栈(pop()),这是避免栈操作出错的关键。
7.例题
题目描述
编写一个 C++ 程序,使用栈判断给定的括号序列是否是「合法的」。
只考虑三种括号:()、[]、{}。 当满足以下条件时,括号序列是合法的:
- 左右括号种类匹配;
- 括号嵌套关系正确;
- 所有左括号都能被匹配。
例如:
([]){}是合法的;([)]、((、())]都是不合法的。
输入格式
一行字符串,只包含字符 (、)、[、]、{、}。 字符串长度不超过 1000。
输出格式
如果括号序列合法,输出 Yes; 否则输出 No。
样例输入
([]){}
样例输出
Yes
约束条件
- 必须使用
std::stack来完成括号匹配; - 时间复杂度应为 O(n)。
参考代码:
cpp
#include<bits/stdc++.h>
using namespace std;
bool whether(char left,char right){
return (left == '(' && right == ')') ||
(left == '[' && right == ']') ||
(left == '{' && right == '}');
}
int main(){
string s;
cin>>s;
stack<char> mode;
for(char c:s){
if(c=='('||c=='['||c=='{'){
mode.push(c);
}
else if(c==')'||c==']'||c=='}'){
if(mode.empty()){
cout<<"No";
return 0;
}
char topchar=mode.top();
mode.pop();
if(!whether(topchar,c)){
cout<<"No";
return 0;
}
}
}
if(mode.empty()){
cout<<"Yes";
}
else{
cout<<"No";
}
return 0;
}