表达式求值 中缀表达式求值 中缀表达式转后缀表达式

经典问题:给出一个表达式,求其运算后的结果。

如:

思路:

  1. 首先需要将中缀表达式转化为后缀表达式
  2. 然后通过后缀表达式求值

第一步(中缀表达式->后缀表达式)的思路:

         定义一个操作符栈stack<char> s,一个队列queue<string>q用来存放后缀表达式,一个map用来存放运算符的优先级

         循环读取字符串的每一个字符c:

  1. 若c为'(':入栈
  2. 若c为')':出栈,一直出到栈顶为'(',将出栈的运算符push到q中,将'('出栈
  3. 若c为'+','-','*','/'其中一个,根据优先级,将优先级大于等于c的运算符出栈push到q中,然后将c入栈
  4. 若c为数字,则定义一个string temp = "";然后循环读取下一个字符,执行temp+=c,直到不是数字和小数点。然后将temp入队
  5. 执行1-4直到读取了每一个字符,然后将s中剩下的操作符push到q中,q即为所求后缀表达式

第二步(后缀表达式求值):

        定义一个queue<string>q2 = q,一个stack<double> sd用来存放操作数

  1. 这一步很简单,从q中读取string.若第一个字符为数字,则将该string转化为double入栈
  2. 若第一个字符不是数字,说明是操作符,则分别定义double d1, d2,为sd的头两个操作数。然后执行这个操作符(注意d1, d2的运算顺序),将结果入栈
  3. 执行1-2直到q为空,此时sd只剩一个最终结果。

代码:

#include<bits/stdc++.h>
#include<queue>
using namespace std;

map<char, int>p;	//操作符优先级 
stack<char> s;		//操作符栈 
stack<double> sd;	//操作数栈,通过后缀表达式求值时需要 
queue<string> q, q2;	//后缀表达式队列

//中缀转后缀表达式 
void f(string str){
	for(int i = 0;i < str.length();i++){
		char c = str[i];
		string d = "";
		if(c == '('){								//左括号入栈
			s.push(c);
		} else if(c == ')'){						//右括号,出栈到左括号为止,并将操作符输出到后缀表达式
			while(!s.empty() && s.top() != '('){
				d += s.top();
				q.push(d);
				s.pop();
			} 
			s.pop();								//弹出左括号 
		} else if(c == '+' || c == '-' || c == '*' || c == '/'){	//如果是操作符,弹出所有优先级大于等于该运算符的栈顶元素 
			while(!s.empty() && p[s.top()] >= p[c]){				//然后将该操作符入栈 
				d += s.top();
				q.push(d);
				s.pop();
				d = "";
			} 
			s.push(c);
		} else {
			string temp = "";
			int j;
			for(j = i;j < str.length();j++){
				char t = str[j];
				if(isdigit(t) || t == '.'){
					temp += t;
				} else {
					break;
				}
			}		
			i = j - 1;
			q.push(temp);
		}
	}
	while(!s.empty()){
		string temp = "";
		temp += s.top();
		q.push(temp);
		s.pop();
	} 
} 

double to(string str){
	const char *ss = str.data();
	return atof(ss);
} 

//后缀表达式求值 
void cal(){
	while(!q2.empty()){
		string str = q2.front();
		q2.pop();
		char tt = str[0];
		if(isdigit(tt)){
			double temp = to(str);
			sd.push(temp);
		}else{
			char c = str[0];
			double t1 = sd.top();		//第二操作数 
			sd.pop();
			double t2 = sd.top();		//第一操作数 
			sd.pop();
			double num;					//结果 
			switch(c){
				case '+':
					num = t2 + t1;
					break;
				case '-':
					num = t2 - t1;
					break;
				case '*':
					num = t2 * t1;
					break;
				case '/':
					num = t2 / t1;
					break;
			}
			sd.push(num); 
		}
	} 
	cout<<sd.top();
}

int main(){
	p['+'] = p['-'] = 1;
	p['*'] = p['/'] = 2;
	string str;
	cin>>str;
	f(str);			//处理字符串 
	q2 = q;
	while(!q.empty()){
		cout<<q.front()<<" ";
		q.pop();
	}
	cout<<endl;
	cal();
}

 

相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页