计算后缀表达式

一、通过栈把中缀表达式转换为后缀表达式的步骤:

从左至右扫描中缀表达式,

if(遇到数字){

    加入后缀表达式

}else if(遇到 ‘(’ ){

    入栈

}else if(遇到 ‘)’ ){

    依次将栈中元素出栈并加入到后缀表达式,直到遇到 ‘(’ 并将其从栈中删除

}else if(遇到运算符op){

    if(栈顶元是 ‘(’ ){

        op入栈

    }else{

        if(高于栈顶运算符优先级){

            op入栈

        }else{

            依次将比op优先级高的和相等的运算符出栈加入到后缀表达式,

            直到遇到比op优先级低的运算符或左括号(低优先级运算符或左括号不出栈)或栈空为止

            op入栈

        }

    }

}

扫描完毕后栈中所有剩下的运算符出栈加入到后缀表达式

二、通过后缀表达式计算表达式的值的步骤:

顺序扫描表达式的每一项

if(遇到操作数){

    入栈

}else if(遇到操作符op){

    连续从栈中退出两个操作数Y和X(先出栈的为Y)

    将 X<op>Y的结果入栈

}

表达式扫描完毕后栈顶元素就是所求的结果

三、计算后缀表达式的代码:

#include <cassert>
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <map>
using std::cout;
using std::endl;
using std::string;
using std::vector;
using std::stack;
using std::map;
class CalcExpress
{
	private:
		enum factorTag{LB,RB,NUM,ADD=10,MINU,MULT = 20,DIV,UNARY=30};//()1 +-*/-//类型标记
		//enum设置默认值10,20是为了区分+- */ -(负号),使得相差较大,便于区别
		static map<char,enum factorTag> tagPair;//mapTag
		typedef std::pair<string,enum factorTag> ExpType;//类型,如<'+',ADD>
		static bool isError;//出错标识
		//------------TEST
	public:

		static void display(const string & s,const vector<ExpType> & x){
			cout<<s<<":"<<endl;
			for(auto & elem:x){
				cout<<elem.first<<"\t\t"<<elem.second<<endl;
			}
			cout<<endl;
		}

		static void display(const vector<ExpType> & x){
			cout<<"----"<<endl;
			for(auto & elem:x){
				cout<<elem.first<<"\t\t"<<elem.second<<endl;
			}
			cout<<endl;
		}

		static void test(){
			string s1("(1+2*-35)/34");
			string s2("-1/2-10-(-333+1)");
			string s3("-(153+2*3)/4");
			string s4("(1+2)*3");
			string s5 = "1--2*3/(2/-3-5)";
			vector<ExpType> vecTest;
			//strToExpress(s1,vecTest);display(s1,vecTest);
			//strToExpress(s2,vecTest);display(s2,vecTest);
			//strToExpress(s3,vecTest);display(s3,vecTest);
			vector<ExpType> inExp,postExp;
			string s = s5;
			strToExpress(s,inExp);
			display(s,inExp);
			inExpToPostExp(inExp,postExp);
			display(postExp);
			double ret = calcExpressProcess(postExp);
			if(!isError){
				cout<<"result = "<<ret<<endl;
			}else{
				cout<<"process error"<<endl;
			}
		}
		//------------TEST

	public:
		static double calcExpress(const char * str){
			if(!str){
				isError = true;
				return 0;
			}
			string cppString(str);
			//判断字符串是否是合法表达式
			if(!isValidExpress(cppString)){
				isError = true;
				return 0;
			}
			double ret = 0;
			isError = false;
			vector<ExpType> express;//数组保存每一个项
			strToExpress(cppString,express);//将表达式的每一项存到数组
			ret = calcExpressProcess(express);
			return ret;
		}
	private:


		static bool isValidExpress(const string & cppString){//判断表达式是否合法
			//待补充完整
			return true;
		}

		static void strToExpress(const string & cppString,vector<ExpType> & express){//将string转成ExpType表达式类型
			//(1+2*-3)/34
			//-1/2-1-(-3+1)
			//-(1+2*3)/4
			express.clear();
			size_t preIdx = 0;
			size_t size = cppString.size(); 
			enum factorTag flag;
			for(size_t i = 0;i<size;++i){
				preIdx = i;//k记录数字的第一个位置
				if(cppString[i] == '-'){
					if(i==0 || (cppString[i-1] != ')' && !::isdigit(cppString[i-1]))){
						//-作为负号的场景:前面不是数字或者)
						flag = UNARY;
					}else{//减号
						flag = MINU;
					}
				}else if(isdigit(cppString[i])){//数字
					while(i<size && isdigit(cppString[i])){
						++i;	
					}
					--i;
					flag = NUM;
				}else{
					switch(cppString[i]){
						case '+':
							flag = ADD;break;
						case '*':
							flag = MULT;break;
						case '/':
							flag = DIV;break;
						case '(':
							flag = LB;break;	
						case ')':
							flag = RB;break;
						default:
							isError = true;
							cout<<"express ERROR"<<endl;
							return;
					}
				}
				express.push_back(ExpType(string(cppString,preIdx,i-preIdx+1),flag));
			}
		}


		static void inExpToPostExp(const vector<ExpType> & inExp,vector<ExpType> & postExp){
			postExp.clear();
			postExp.reserve(inExp.size());
			stack<ExpType> stk;//栈
			for(auto & inTerm:inExp){
				if(inTerm.second == NUM){//数值
					postExp.push_back(inTerm);
				}else if(inTerm.second == RB){//右括号
					while(!stk.empty()){
						if(stk.top().second == LB){//左括号
							stk.pop();
							break;
						}else{
							postExp.push_back(stk.top());
							stk.pop();
						}
					}
				}else if(inTerm.second == LB){//左括号
					stk.push(inTerm);
				}else{//运算符
					while(
							!stk.empty() && \
							(\
							 (inTerm.second <= stk.top().second) || ((inTerm.second - stk.top().second) == 1) \
							)\
						 ){//如果栈顶是高优先级或平级运算符
						postExp.push_back(stk.top());
						stk.pop();
					}
					stk.push(inTerm);
				}
			}
			while(!stk.empty()){
				postExp.push_back(stk.top());
				stk.pop();
			}
		}

		static double calcExpressProcess(const vector<ExpType> & postExp){
			stack<double> calcStk;//栈用于记录中间过程的值
			for(auto & postTerm:postExp){
				if(postTerm.second == NUM){//数值
					calcStk.push(stod(postTerm.first));
				}else{//运算符
					if(postTerm.second == UNARY){//负号
						auto & val = calcStk.top();
						val = -val;
					}else{//其他双目运算符
						double num2 = calcStk.top();
						calcStk.pop();
						double num1 = calcStk.top();
						calcStk.pop();
						if(postTerm.second == DIV){//判断是否发生除零
							const double limit = 0.000000001;
							if(num2 >= -1*limit && num2 <= limit){//num2为0
								isError = true;
								cout<<"error,Divide zero"<<endl;
								abort();
							}
						}
						double val = 0;
						switch(postTerm.second){
							case ADD:
								val = num1 + num2;break;
							case MINU:
								val = num1 - num2;break;
							case MULT:
								val = num1 * num2;break;
							case DIV:
								val = num1*1.0 / num2;break;
							default:
								isError = true;
								cout<<"express ERROR"<<endl;
								return 0;
						}
						calcStk.push(val);
					}
				}
			}
			if(calcStk.size() != 1){//最后栈中剩下的数就是结果
				isError = true;
				cout<<"express ERROR"<<endl;
				return 0;
			}
			return calcStk.top();
		}

};
bool CalcExpress::isError = false;
int main(){
	CalcExpress::test();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/creativele/article/details/81710049