栈是计算机中经典的数据结构,简单的说,栈就是限制在一端进行插入删除操作的线性表。
栈有两种最重要的操作,即 pop(从栈顶弹出一个元素)和 push(将一个元素进栈)。
思想:先进后出,后进先出。可以理解为一些书,摆放时一本本堆起来,从低到高;取时从高到低一本本来取。
C++的STL库让我们更便利地写一个栈,而且空间开多少用多少,不必担心浪费。当然,手写栈也是可以的。
例题
Luogu 1739 表达式括号匹配
这道题数据简单,用一下栈的思想就能解决问题,不必写栈难多少。
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
char c;//输入的字符。本题中,除了两个括号和@,其他字符都没有用。
int s;//记录括号的情况
/*
“匹配”指的是(和)最终都能两两凑成一对。
不匹配情况:(开头但是数目不相等, 如())
)开头,如)()(,这一条出于惯性思维,我们不容易想到
*/
int main(){
do{
cin>>c;
//出现(则s=s+1来记录,出现)则s=s-1来记录。那么一对()可以实现“抵消”
if(c=='('&&s>-1) s++;//表达式(出现而且它前面没有落单的)
if(c==')'&&s>=0) s--;//前面无匹配或匹配正常
else if(c==')'&&s<0) break;
}while(c!='@');
//cin>>c是可以写在以c为条件的do while中的,有些神奇。
if(s==0) cout<<"YES";//“抵消”成功,说明能匹配
else cout<<"NO";//只要s不为0,那么表达式括号匹配失败
return 0;
}
Luogu1427 小鱼的数字游戏
1.手写栈
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define MAXN 105
int top,a[MAXN],c;
int main(){
while(cin>>c){
if(c==0) break;//如果读入的是0那么不会将它存进数组,读入结束
else a[top++]=c;//在这种写法之下,数字从a[0]开始存储。
//数组稍微开大一些可以防止越界
}
while(top>=1){
cout<<a[--top]<<" ";
}
return 0;
}
2.STL栈
1)vector
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<vector>
using namespace std;
vector<int>a;
int c;
//要注意vector是从a[0]开始存储a.size()个元素
int main(){
while(cin>>c){
if(c==0) break;
a.push_back(c);
}
while(!a.empty()){
cout<<a.back() <<' ';
a.pop_back() ;
/*
这一部分输出也可以写成:
for(int i=a.size()-1;i>=0;i--) //a.size()返回a中元素的个数
cout<<a[i]<<" ";
*/
}
return 0;
}
2)stack
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<stack>//栈的头文件
using namespace std;
stack<int>a;
int c;
int main(){
while(cin>>c){
if(c==0) break;
a.push(c);
}
while(!a.empty()){
cout<<a.top()<<' ';//输出顶部元素
a.pop() ;//弹出顶部元素
}
return 0;
}
Luogu5788 【模板】单调栈
stack
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<stack>
using namespace std;
#define MAXN 3000005
int n,a[MAXN],f[MAXN];
//a记录输入的数组,f记录答案
stack<int>s;//s用于存储下标
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=n;i>=1;i--){//从数组之中最后一个元素开始查找
while(!s.empty()&&a[s.top() ]<=a[i])
//栈不为空而且栈顶元素比当前数小
s.pop() ;//弹出,反正之后也不会需要
f[i]=s.empty()?0:s.top();//记录答案
s.push(i); //当前i入栈
}
//i=n的状态比较特殊,for只执行20行,自己可以模拟一下
for(int i=1;i<=n;i++)
printf("%d ",f[i]);
return 0;
}