1、简单栈
1331:【例1-2】后缀表达式的值
【题目描述】
从键盘读入一个后缀表达式(字符串),只含有0-9组成的运算数及加(+)、减(—)、乘(*)、除(/)四种运算符。每个运算数之间用一个空格隔开,不需要判断给你的表达式是否合法。以@作为结束标志。
比如,16–9*(4+3)转换成后缀表达式为:16□9□4□3□+*–,在字符数组A中的形式为:
栈中的变化情况:
运行结果:-47
提示:输入字符串长度小于250,参与运算的整数及结果之绝对值均在264范围内,如有除法保证能整除。
【输入】
一个后缀表达式。
【输出】
一个后缀表达式的值。
【输入样例】
16 9 4 3 +*-@
【输出样例】
-47
<代码1>手写栈
#include<bits/stdc++.h>
using namespace std;
long long sta[1001];
int top;
int main()
{
string s;
getline(cin,s);
int l=s.size();
for(int i=0;s[i]!='@';i++)
{
if(s[i]>='0'&&s[i]<='9')
{
long long x=0;
while(isdigit(s[i]))x=x*10+s[i++]-48;
sta[++top]=x;
}
if(s[i]=='+')sta[top-1]+=sta[top],top--;
if(s[i]=='-')sta[top-1]-=sta[top],top--;
if(s[i]=='*')sta[top-1]*=sta[top],top--;
if(s[i]=='/')sta[top-1]/=sta[top],top--;
}
cout<<sta[1];
return 0;
}
<代码2>STL栈
#include<bits/stdc++.h>
using namespace std;
stack<long long>sta;
int main()
{
string s;
getline(cin,s);
int l=s.size();
for(int i=0;s[i]!='@';i++)
{
if(s[i]>='0'&&s[i]<='9')
{
long long x=0;
while(isdigit(s[i]))x=x*10+s[i++]-48;
sta.push(x);
}
if(s[i]=='+'||s[i]=='-'||s[i]=='*'||s[i]=='/')
{
long long x=sta.top();sta.pop();
long long y=sta.top();sta.pop();
if(s[i]=='+')y+=x;
if(s[i]=='-')y-=x;
if(s[i]=='*')y*=x;
if(s[i]=='/')y/=x;
sta.push(y);
}
}
cout<<sta.top();
return 0;
}
2、栈原理
1357:车厢调度(train)
【题目描述】
有一个火车站,铁路如图所示,每辆火车从A驶入,再从B方向驶出,同时它的车厢可以重新组合。假设从A方向驶来的火车有n节(n≤1000),分别按照顺序编号为1,2,3,…,n。假定在进入车站前,每节车厢之间都不是连着的,并且它们可以自行移动到B处的铁轨上。另外假定车站C可以停放任意多节车厢。但是一旦进入车站C,它就不能再回到A方向的铁轨上了,并且一旦当它进入B方向的铁轨,它就不能再回到车站C。
负责车厢调度的工作人员需要知道能否使它以a1,a2,…,an的顺序从B方向驶出,请来判断能否得到指定的车厢顺序。
【输入】
第一行为一个整数n,其中n≤1000,表示有n节车厢,第二行为n个数字,表示指定的车厢顺序。
【输出】
如果可以得到指定的车厢顺序,则输出一个字符串“YES
”,否则输出“NO
”(注意要大写,不包含引号)。
【输入样例】
5
5 4 3 2 1
【输出样例】
YES
<代码1>枚举
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+3;
int n,a[N];
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(a[i]>a[j])
for(int k=j+1;k<=n;k++)
if(a[k]>a[j]&&a[k]<a[i])
{
cout<<"NO"<<endl;
return 0;
}
cout<<"YES"<<endl;
return 0;
}
<代码2>栈思想
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+3;
int n,cnt,a[N];
stack<int>sta;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
{
while(cnt<=a[i])
{
sta.push(cnt);
cnt++;
}
if(a[i]!=sta.top())
{
cout<<"NO"<<endl;
return 0;
}
sta.pop();
}
cout<<"YES"<<endl;
return 0;
}
3、括号匹配
1353 表达式括号匹配(stack)
【题目描述】
假设一个表达式有英文字母(小写)、运算符(+,—,∗,/)和左右小(圆)括号构成,以“@”作为表达式的结束符。请编写一个程序检查表达式中的左右圆括号是否匹配,若匹配,则返回“YES”;否则返回“NO”。表达式长度小于255,左圆括号少于20个。
【输入】
一行数据,即表达式。
【输出】
一行,即“YES” 或“NO”。
【输入样例】
2*(x+y)/(1-x)@
【输出样例】
YES
【样例输入2】
(25+x)*(a*(a+b+b)@
【样例输出2】
NO
<代码>
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+3;
int top;
int main()
{
string s;
getline(cin,s);
int l=s.size();
for(int i=0;s[i]!='@';i++)
{
if(s[i]=='(')top++;
if(s[i]==')')
{
if(top==0){cout<<"NO"<<endl;return 0;}
top--;
}
}
if(top)cout<<"NO"<<endl;
else cout<<"YES"<<endl;
return 0;
}
4、中缀表达式
1356:计算(calc)
【题目描述】
小明在你的帮助下,破密了Ferrari设的密码门,正要往前走,突然又出现了一个密码门,门上有一个算式,其中只有“(”,“)”,“0-9”,“+”,“-”,“*”,“/”,“^”,求出的值就是密码。小明数学学得不好,还需你帮他的忙。(“/”用整数除法)
【输入】
共1行,为一个算式。
【输出】
共1行,就是密码。
【输入样例】
1+(3+2)*(7^2+6*9)/(2)
【输出样例】
258
<代码>
#include<bits/stdc++.h>
using namespace std;
stack<int>num;
stack<char>op;
int cmp(char c)
{
if(c=='+'||c=='-')return 0;
if(c=='*'||c=='/')return 1;
if(c=='^')return 2;
if(c=='(')return -1;
}
void clac()
{
char c=op.top();op.pop();
int x=num.top();num.pop();
int y=num.top();num.pop();
if(c=='+')y+=x;
if(c=='-')y-=x;
if(c=='*')y*=x;
if(c=='/')y/=x;
if(c=='^')y=pow(y,x);
num.push(y);
}
int main()
{
string s;
getline(cin,s);
s='('+s+')';
int l=s.size();
for(int i=0;i<l;i++)
{
if(isdigit(s[i]))
{
int x=0;
while(isdigit(s[i]))
x=x*10+s[i++]-48;
i--;
num.push(x);
}
if(s[i]=='(')op.push(s[i]);
if(s[i]==')')
{
while(op.top()!='(') clac();
op.pop();//弹出左括号
}
if(s[i]=='+'||s[i]=='-')
{
while(cmp(op.top())>=0)clac();
op.push(s[i]);
}
if(s[i]=='*'||s[i]=='/')
{
while(cmp(op.top())>=1)clac();
op.push(s[i]);
}
if(s[i]=='^')op.push(s[i]);
}
cout<<num.top()<<endl;
r