ybt 1356 计算(calc)

题目链接

看到题目,毫无疑问,这是道大模拟+栈。

对于中缀表达式,不做任何处理来计算出结果是十分麻烦的,所以我利用了刚刚学的栈来转换成后缀表达式来做。

将中缀表达式转换为后缀表达式,遵循如下法则:

  1. 遇到数字,直接将数字输出;

  2. 遇到运算符,比较其与栈顶的优先级,如果栈顶运算符的优先级比当前运算符高,则一直输出并弹出栈顶元素直到栈顶的优先级比当前运算符低为止(或者遇到正括号了),将运算符压入。

  3. 遇到正括号,直接压入,遇到反括号,持续弹出运算符直到遇到最近的正括号为止,然后弹出正括号,但正反括号均不输出。(注意:遇到N/(A*B+C)这种情况时,弹出的乘号是直接输出,而非转换后存在括号里)

最后注意把运算符弹出完。

代码如下
#include <bits/stdc++.h>
using namespace std;
string str;
char sc[100005];//运算符栈
map<char,int>a;//运算符优先级映射
struct node{
	int type;//type为1表示运算符,type为0表示数字
	int num;
}st[200005];//存储后缀表达式
int top=0,toc=0;
int main() {
	a['+']=1;//定义优先级
	a['-']=1;
	a['*']=2;
	a['/']=2;
	a['^']=3;
	cin>>str;
	for(int i=0;i<str.size();i++){
		if(str[i]<='9'&&str[i]>='0'){//转换数字
			int sum=0;
			while(str[i]<='9'&&str[i]>='0'){
				sum=sum*10+str[i]-'0';
				i++;
			}
			i--;
			st[++top].type=0;
			st[top].num=sum;//直接输出
		}else{
			switch(str[i]){
				case '(':{//正括号
					sc[++toc]=str[i];
					break;
				}
				case ')':{//反括号
					while(sc[toc]!='('){
						st[++top].type=1;
						st[top].num=(int)sc[toc];
						toc--;
					}
					toc--;
					break;
				}
				default:{//运算符
					while(a[sc[toc]]>=a[str[i]]&&sc[toc]!='('){
						st[++top].type=1;
						st[top].num=(int)sc[toc];
						toc--;
					}
					sc[++toc]=str[i];
					break;
				}
			}
		}
		/*
		for(int j=1;j<=toc;j++){
			cout<<sc[j];
		}
		cout<<endl;
		for(int j=1;j<=top;j++){
			if(st[j].type==0){
				cout<<st[j].num;
			}else{
				cout<<(char)st[j].num;
			}
		}
		cout<<endl;
		getchar();
		*/
	}
	while(toc){//记得弹出
		st[++top].type=1;
		st[top].num=(int)sc[toc];
		toc--;
	}
	/*
	for(int i=1;i<=top;i++){
		if(st[i].type==0){
			cout<<st[i].num<<' ';
		}else{
			cout<<(char)st[i].num<<' ';
		}
	}
	cout<<endl;
	*/
	return 0;
}

​ 然后是将后缀表达式计算出来,对于计算机而言,后缀表达式没有优先级之类麻烦的东西,可以大胆地去算。运算法则如下:

  1. 如果遇到数字,直接压入栈中。
  2. 如果遇到运算符,将栈顶两个元素弹出进行计算,再将计算的结果压入栈中。(注意:减法、除法、乘方是有先后顺序的,切记不可搞错)。
代码如下
#include <bits/stdc++.h>
using namespace std;
string str;
struct node{
	int type;
	int num;
}st[200005];
int num[100005];
int top=0,ton=0;
int main() {
	for(int i=1;i<=top;i++){
		if(st[i].type==0){
			num[++ton]=st[i].num;//数字入栈
		}else{
			int x,y,z;
			switch((char)st[i].num){//字符计算
				case '+':{
					x=num[ton--];
					y=num[ton];
					z=x+y;
					num[ton]=z;
					break;
				}
				case '-':{
					x=num[ton--];
					y=num[ton];
					z=y-x;//注意顺序
					num[ton]=z;
					break;
				}
				case '*':{
					x=num[ton--];
					y=num[ton];
					z=x*y;
					num[ton]=z;
					break;
				}
				case '/':{
					x=num[ton--];
					y=num[ton];
					z=y/x;//注意顺序
					num[ton]=z;
					break;
				}
				case '^':{
					x=num[ton--];
					y=num[ton];
					z=pow(y,x);//注意顺序
					num[ton]=z;
					break;
				}
			}
		}
		/*
		for(int i=1;i<=ton;i++){
			cout<<num[i]<<' ';
		}
		cout<<endl;
		getchar();
		*/
	}
	cout<<num[1];//最后的结果即为数字栈顶
	return 0;
}

​ 最后总的代码就是这样了:

100分AC代码:
#include <bits/stdc++.h>
using namespace std;
string str;
char sc[100005];
map<char,int>a;
struct node{
	int type;
	int num;
}st[200005];
int num[100005];
int top=0,toc=0,ton=0;
int main() {
	a['+']=1;
	a['-']=1;
	a['*']=2;
	a['/']=2;
	a['^']=3;
	cin>>str;
	for(int i=0;i<str.size();i++){
		if(str[i]<='9'&&str[i]>='0'){
			int sum=0;
			while(str[i]<='9'&&str[i]>='0'){
				sum=sum*10+str[i]-'0';
				i++;
			}
			i--;
			st[++top].type=0;
			st[top].num=sum;
		}else{
			switch(str[i]){
				case '(':{
					sc[++toc]=str[i];
					break;
				}
				case ')':{
					while(sc[toc]!='('){
						st[++top].type=1;
						st[top].num=(int)sc[toc];
						toc--;
					}
					toc--;
					break;
				}
				default:{
					while(a[sc[toc]]>=a[str[i]]&&sc[toc]!='('){
						st[++top].type=1;
						st[top].num=(int)sc[toc];
						toc--;
					}
					sc[++toc]=str[i];
					break;
				}
			}
		}
		/*
		for(int j=1;j<=toc;j++){
			cout<<sc[j];
		}
		cout<<endl;
		for(int j=1;j<=top;j++){
			if(st[j].type==0){
				cout<<st[j].num;
			}else{
				cout<<(char)st[j].num;
			}
		}
		cout<<endl;
		getchar();
		*/
	}
	while(toc){
		st[++top].type=1;
		st[top].num=(int)sc[toc];
		toc--;
	}
	/*
	for(int i=1;i<=top;i++){
		if(st[i].type==0){
			cout<<st[i].num<<' ';
		}else{
			cout<<(char)st[i].num<<' ';
		}
	}
	cout<<endl;
	*/
	for(int i=1;i<=top;i++){
		if(st[i].type==0){
			num[++ton]=st[i].num;
		}else{
			int x,y,z;
			switch((char)st[i].num){
				case '+':{
					x=num[ton--];
					y=num[ton];
					z=x+y;
					num[ton]=z;
					break;
				}
				case '-':{
					x=num[ton--];
					y=num[ton];
					z=y-x;//注意 
					num[ton]=z;
					break;
				}
				case '*':{
					x=num[ton--];
					y=num[ton];
					z=x*y;
					num[ton]=z;
					break;
				}
				case '/':{
					x=num[ton--];
					y=num[ton];
					z=y/x;//注意 
					num[ton]=z;
					break;
				}
				case '^':{
					x=num[ton--];
					y=num[ton];
					z=pow(y,x);//注意 
					num[ton]=z;
					break;
				}
			}
		}
		/*
		for(int i=1;i<=ton;i++){
			cout<<num[i]<<' ';
		}
		cout<<endl;
		getchar();
		*/
	}
	cout<<num[1];
	return 0;
}

大功告成!

原文地址:https://www.cnblogs.com/returnG/p/13088965.html