• 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;
    }
    

    大功告成!

  • 相关阅读:
    第一次随笔
    SDN第二次上机作业
    SDN第二次作业
    个人作业——软件产品案例分析
    SDN第一次上机作业
    SDN第一次作业
    个人技术博客(1/2)android布局技巧
    个人技术博客(α)
    团队作业——随堂小测(同学录)
    Alpha冲刺报告(2/12)(麻瓜制造者)
  • 原文地址:https://www.cnblogs.com/returnG/p/13088965.html
Copyright © 2020-2023  润新知