山东大学数据结构实验五:堆栈的应用

实验内容

①输入一个数学表达式(假定表达式输入格式合法),计算表达式结果并输出。

②数学表达式由单个数字和运算符“+”、“-”、“*”、“/”、“(、) ”构成,例如 2 + 3 * ( 4 + 5 ) - 6 / 4。

③变量、输出采用整数,只舍不入。

实验步骤

  首先我参考了ppt的内容,总结出这类问题的解法。即:先把中缀表达式转换成后缀表达式,然后通过堆栈再把后缀表达式求值得出结果。

①中缀表达式转化成后缀表达式:

举例分析,中缀表达式a + b*c + (d * e + f) * g,其转换成后缀表达式则为a b c * + d e * f  + g * +。转换过程需要用到栈,具体过程如下:

1)如果遇到操作数,我们就直接将其输出。

2)如果遇到操作符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中。

3)如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括号只弹出并不输出。

4)如果遇到任何其他的操作符,如(“+”, “*”,“(”)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的操作符压入到栈中。有一点需要注意,只有在遇到" ) "的情况下我们才弹出" ( ",其他情况我们都不会弹出" ( "。

5)如果我们读到了输入的末尾,则将栈中所有元素依次弹出。

②后缀表达式求值:

从前向后扫描:

A.遇到数字,入栈

B.遇到符号,弹出两个数,然后计算(栈底的元素在前,栈顶的元素在后面),将计算的结果入栈

③编写程序:

定义两个栈和一个字符串

string aft;//存后缀表达式

stack<char>temp;//存符号

stack<int> ans;//保存结果

然后按逻辑编写两个方法,最后按要求输出。本次实验写了一个小时,调试bug用了两个小时,感觉逻辑没问题,反复看了十几遍代码,都没找到问题。最后发现,如果中缀表达式中的*无法消除符号栈中的内容时,一定要break,不然会陷入死循环,改正这个bug后程序就运行正常了。

④运行结果举例:

本次实验主要代码:
#include<bits/stdc++.h>
using namespace std;

string aft;//存后缀表达式 
stack<char>temp;//存符号 
stack<int> ans;//保存结果
void mid_to_aft(string &s){
	for(int i=0;i<s.size();i++){
		if( s[i]=='('){
			temp.push(s[i]);
		}
		else if(s[i]==')'){
			while(!temp.empty()){
				if(temp.top()=='(')
				{
					temp.pop();
					break;
				}
				aft.push_back(temp.top());
				temp.pop();
			}
		}
		else if(s[i]=='+'||s[i]=='-'){
			while(!temp.empty()){
				if(temp.top()=='('){
					break;
				}
				else{
					//cout<<temp.top();//
					aft.push_back(temp.top());
				    temp.pop();
				}
			}
			temp.push(s[i]);
		}
		else if(s[i]=='*'||s[i]=='/'){
			while(!temp.empty()){
				if(temp.top()=='('){
					break;
				}
				else if(temp.top()=='*'||temp.top()=='/'){
					//cout<<temp.top();//
					aft.push_back(temp.top());
				    temp.pop();
				}
				else{
					break;
				}
			}
			temp.push(s[i]);
		}
		else if(s[i]>='0'&&s[i]<='9'){
			aft.push_back(s[i]);
		}
	}
	while(!temp.empty()){
					aft.push_back(temp.top());
				    temp.pop();
				}
} 
void cal_and_print(string &s){
	for(int i=0;i<s.size();i++){
		
		if(s[i]>='0'&&s[i]<='9'){
			ans.push((int)(s[i]-'0'));
		}
		else{
			int num2=ans.top();
			ans.pop();
			int num1=ans.top();
			ans.pop();
			if(s[i]=='+'){
				ans.push(num1+num2);
			}
			if(s[i]=='-'){
				ans.push(num1-num2);
			}
			if(s[i]=='*'){
				ans.push(num1*num2);
			}
			if(s[i]=='/'){
				ans.push(num1/num2);
			}
		}
	}
	cout<<ans.top()<<endl;
}
int main(){
	cout<<"Input"<<endl;
	string input;
	cin>>input;
	cout<<"Output"<<endl;
	mid_to_aft(input);
	cal_and_print(aft);
	cout<<"End0";
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值