栈
栈
栈是一种先进后出的数据结构,你可以把栈想象成一个羽毛球筒子。先放的,反而会在底下,后方的则在上面。
栈的实现方法
手写栈
我们设置一个指针 \(top\) 表示当前的栈顶下标,用一个数组 \(a\) 来模拟栈。
入栈
当一个元素入栈时,\(top\) 加1, \(a_{top}\) 为入栈元素。
void push(int x){
top++;
a[top] = x;
}
出栈
当一个元素出栈时,\(top\) 减1。
void pop(){
top--;
}
获取栈顶元素
返回 \(a_{top}\) 即可.
int top(){
return a[top];
}
判断栈是否为空
当 \(top\) 为 \(0\) 时,说明栈是空的。
bool isEmpty(){
return !top;
}
获取栈元素数量
输出 \(top\) 即可。
int size(){
return top;
}
/注意,这些函数有些为重名,不要照搬。
STL函数大法
看到上面的一大堆代码,是不是感觉很烦,其实呢,c++给我们内置了栈这种数据结构。
stack<int>a; //初始化栈,int可以替换成char, vector<int>, string, pair<int,int>等
a.push(x); // 将x入栈
a.pop(x); // 弹出栈顶元素
a.size(); // 获取元素数量
a.top(); // 获取栈顶元素
写到这,作者不禁从内心赞美STL的好啊!
来道例题
大家都看到这里了,可能有些人都不知道栈有什么用,我接下来带大家做几道例题来认识一下吧!
P1739 表达式括号匹配
先看描述:
假设一个表达式有英文字母(小写)、运算符(+、-、*、/)和左右小(圆)括号构成,以 @ 作为表达式的结束符。请编写一个程序检查表达式中的左右圆括号是否匹配,若匹配,则输出 YES;否则输出 NO。表达式长度小于 \(255\),左圆括号少于 \(20\) 个。
很明显,我们需要检查括号是否匹配,我们可以分几种类型来讨论:
-
()这种很明显是合法的。 -
(())这种很明显也是合法的。 -
([)]这种很明显不合法。
我们发现,括号遵守就近匹配原则,也就是最近的一个左括号匹配到最近的一个右括号。这不正好匹配栈的特性吗!所以这道题很明显要用栈来做。
#include <bits/stdc++.h>
using namespace std;
stack<char>charList; // 初始化一个char类型的栈
char temp;
int main(){
while(temp!='@'){
cin>>temp;
if(temp=='('){
charList.push(temp);
}
if(temp==')'){
if(charList.size()<=0){ // 如果所有的括号都匹配完了,还有左括号待匹配的话,说明
cout<<"NO"<<endl; // 该表达式不合法。
return 0;
}
else{
charList.pop(); // 匹配成功,弹出。
}
}
}
if(charList.size()==0){
cout<<"YES"<<endl; // 栈空,说明全部匹配,表达式合法。
return 0;
}
cout<<"NO";
}
单调栈
单调栈是栈的一种变种,单调栈中的元素始终是递增的。
让我们模拟一遍单调栈的运行过程,这里的单调栈是单调递增栈。
我们现在有 6 个数 5,2,3,4,1,6
首先我们要明白,我们存放的是下标。然后,我们直接把元素放在栈顶,会破坏它的单调性。所以我们需要吐出栈顶的元素,使得我们当前的元素再加进去不会破坏它的单调性。
- 我们当前栈内没有元素,将 5 加入。现在栈内元素应该是 1。
- 当前元素为 2,我们发现加入之后不能单调,于是吐出 5,加入 2。当前栈内元素为 2。
- 接下来是 3,4。我们发现加入不会破坏单调性,于是直接加入,栈内元素 2,3,4。
- 遇到 1,只能吐出栈内所有元素,加入 1。
- 最后加入 6。整个算法流程完成。
实现
#include<stack>
using namespace std;
int n,a[3000005],f[3000005];
stack<int>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(); // 如果栈空,输出0。否则输出栈顶。
s.push(i); // 入栈
}
for(int i=1;i<=n;i++) cout << f[i] << ' ';
return 0;
}

浙公网安备 33010602011771号