08- 栈

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值