• 中缀表达式


    不含括号的中缀表达式

    代码实现

    //直接计算中缀表达式
    //不含括号
    #include<iostream>
    #include<stack>
    #include<string>
    
    using namespace std;
    
    //运算符号优先级比较
    //加减为低级运算,乘除是高级运算;先算乘除
    //return 1 means can calculate, else can not.
    int getPriority( stack<char> operators )
    {
    	if( !operators.empty()  && ( operators.top() == '*' || operators.top() == '/') ){
    		return 1;
    	}
    
    	return 0;
    }
    
    
    //输入操作符栈 和 操作数栈 进行计算
    void calculate(stack<double> &operands, stack<char> &operators)
    {
    	double op1, op2, res;
    	char operation;
    
    	op2 = operands.top();
    	operands.pop();
    	op1 = operands.top();
    	operands.pop();
    
    	operation = operators.top();
    	operators.pop();
    
    	switch( operation ){
    		case '+':
    			res = op1 + op2;
    			break;
    		case '-':
    			res = op1 - op2;	//对顺序有要求
    			break;
    		case '*':
    			res = op1 * op2;
    			break;
    		case '/':
    			res = op1 / op2;	//这个顺序不能反
    			break;
    	
    	}
    
    	//cout << op1 << operation << op2 << "=" << res << endl;	//test
    	operands.push(res);
    
    }
    
    
    int main()
    {
    	stack<double> operands;	//除法运算可能会出现小数
    	stack<char> operators;
    
    	string formula;
    	string number;
    
    	const string numbers = "0123456789";
    	const string operation = "+-*/";
    
    	cin >> formula;
    	for( string::iterator c = formula.begin();  c != formula.end();  c++ ){
    
    		//处理数字
    		if( numbers.find(*c) != string::npos ){
    			while( numbers.find(*c) != string::npos ){
    				number += *c;
    				c++;
    			} 
    			operands.push( stod(number) );
    			number.clear();
    
    		       //读完最后一个数字
    			if ( c == formula.end() ){
    				if( getPriority(operators) == 1 ){	//最后一个操作符可能是乘除
    					calculate(operands, operators);
    				}
    				break;	
    			}
    		}
    
    		//calculate, 先算乘除
    		if( operation.find(*c) != string::npos ){
    			if ( getPriority(operators)  ==  1 ){
    				calculate( operands, operators );
    			}
    			operators.push((*c));
    		}
    	}
    
    
    	//处理剩余的加减
    	while( !operators.empty() ){
    		char operation = operators.top();
    
    		//减法有顺序要求;1-2+3,先执行1-2=-1,再执行-1+3
    		if( operation == '+' ){
    			operators.pop();
    			if( !operators.empty()  &&  operators.top() == '-' ){
    				double tmp = operands.top();
    				operands.pop();
    
    				calculate( operands, operators );
    
    				operators.push(operation);
    				operands.push(tmp);
    			}	
    			else{
    				operators.push(operation);
    				calculate( operands, operators );
    			}
    
    		}
    		else{
    			calculate( operands, operators );
    		}
    
    	}
    	
    	cout << formula << " = " << operands.top() << endl;
    	return 0;
    }
    

    含括号的中缀表达式代码实现

    //直接计算中缀表达式
    //含括号
    #include<iostream>
    #include<deque>
    #include<string>
    
    using namespace std;
    
    
    //运算符号优先级比较
    //return 1 means can calculator, else can not.
    int getPriority( deque<char> operators )
    {
    	if( !operators.empty()  && ( operators.back() == '*' || operators.back() == '/') ){
    		return 1;
    	}
    
    	return 0;
    }
    
    
    double calculate( double op1, double op2, char operation )
    {
    	double res;
    
    	switch( operation ){
    		case '+':
    			res = op1 + op2;
    			break;
    		case '-':
    			res = op1 - op2;	//对顺序有要求
    			break;
    		case '*':
    			res = op1 * op2;
    			break;
    		case '/':
    			res = op1 / op2;	//这个顺序不能反
    			break;
    	}
    
    	//cout << op1 << operation << op2 << "=" << res << endl;	//test
    
    	return res;
    }
    
    void calculator(deque<double> &operands, deque<char> &operators)
    {
    	double op1, op2, res;
    	char operation;
    
    	operation = operators.back();
    	operators.pop_back();
    
    	//这个糟糕的顺序
    	if( operation == '-' ){
    		op1 = operands.back();
    		operands.pop_back();
    		op2 = operands.back();
    		operands.pop_back();
    	}else{
    		op2 = operands.back();
    		operands.pop_back();
    		op1 = operands.back();
    		operands.pop_back();
    	}
    
    
    	res = calculate( op1, op2, operation );
    
    	operands.push_back(res);
    }
    
    
    
    
    int main()
    {
    	deque<double> operands;	//除法运算可能会出现小数; 使用deque,比栈更灵活
    	deque<char> operators;
    
    	string formula;
    	string number;
    
    	const string numbers = "0123456789";
    	const string Operation = "+-*/";
    
    	cin >> formula;
    	for( string::iterator c = formula.begin();  c != formula.end();  c++ ){
    
    		//处理数字
    		if( numbers.find(*c) != string::npos ){
    			while( numbers.find(*c) != string::npos ){
    				number += *c;
    				c++;
    			} 
    			operands.push_back( stod(number) );
    			number.clear();
    
    		       //读完最后一个数字
    			if ( c == formula.end() ){
    				if( getPriority(operators) == 1 ){	//最后一个可能是乘除
    					calculator(operands, operators);
    				}
    				break;	
    			}
    		}
    
    		//处理 + - * /
    		if( Operation.find(*c) != string::npos ){
    			//calculator, 先算乘除
    			if ( getPriority(operators)  ==  1 ){
    				calculator( operands, operators );
    			}
    			operators.push_back((*c));
    		}
    		//处理括号
    		else{
    			if( *c == '(' ){
    				operators.push_back((*c));
    			}
    			//遇到)”时,算出()内算式的值
    			else{	
    				//)前面可能是乘除
    				if(  getPriority(operators) == 1 ){
    					calculator(operands, operators);
    				}
    
    				//此时括号内已经没有乘除
    				deque<double> tmp_oprands;
    				deque<char> tmp_operators;
    				//把()内的算式pop到新的栈
    				while( operators.back() != '(' ){
    					tmp_oprands.push_back(operands.back());
    					operands.pop_back();
    					
    					tmp_operators.push_back(operators.back());
    					operators.pop_back();
    				}
    				tmp_oprands.push_back(operands.back());
    				operands.pop_back();
    				operators.pop_back();	//弹出“(”
    				
    				while(!tmp_operators.empty()){	//计算括号内的算式
    					calculator( tmp_oprands, tmp_operators );
    				}
    
    				operands.push_back( tmp_oprands.back() );	//push结果
    				tmp_oprands.pop_back();
    
    			}
    		
    		}
    	}
    
    
    	//处理剩余的加减
    	double op1, op2, res;
    	char operation;
    	while( !operators.empty() ){
    
    		//因为前面使用的是deque结构而不是stack,所以这里可以从栈底开始读取
    		//(考虑到减法运算过程中的y顺序要求)
    		op1 = operands.front();
    		operands.pop_front();
    		op2 = operands.front();
    		operands.pop_front();
    
    		operation = operators.front();
    		operators.pop_front();
    
    		res = calculate( op1, op2, operation);
    
    		operands.push_front(res);
    	}
    	
    	cout << formula << " = " << operands.back() << endl;
    	return 0;
    }
    

    改进

    前面的算法将加减与乘除分开处理,导致后面运算加减的时候还要考虑减法的运算顺序问题,变得麻烦了。
    下面是改进后的代码

    #include<iostream>
    #include<string>
    #include<stack>
    
    using namespace std;
    
    
    //return the answer of op1 operation op2
    double calculate( double op1, double op2, char operation )
    {
    	double res;
    
    	switch(operation){
    		case '-':
    			res = op1 - op2;
    			break;
    		case '+':
    			res = op1 + op2;
    			break;
    		case '*':
    			res = op1 * op2;
    			break;
    		case '/':
    			res = op1 / op2;
    			break;
    	}
    	
    	cout << op1 << operation << op2 << " = " << res << endl;	//test
    	return res;
    }
    
    
    int getPriority( char operation )
    {
    	//这个优先级很微妙
    	if ( operation == '(' )
    		return 1;
    	else if( operation == '+' ||  operation == '-' )
    		return 2;
    	else if( operation == '*' ||  operation == '/' )
    		return 3;
    }
    
    void calculator( stack<double> &operands,  stack<char> &operators )
    {
    	double op1, op2, ans;
    	char operation;
    
    	op2 = operands.top();
    	operands.pop();
    	op1 = operands.top();
    	operands.pop();
    
    	operation = operators.top();
    	operators.pop();
    
    	ans = calculate( op1, op2, operation );
    
    	operands.push(ans);
    }
    
    
    //(1+2)*33-8/2-9
    
    int main()
    {
    	const string Numbers = "0123456789";
    	const string Operators = "+-*/";
    
    	stack<double> operands;
    	stack<char> operators;
    
    	string formula;
    
    	cin >> formula;
    
    	for( string::iterator c = formula.begin(); c != formula.end();  c++ ){
    	
    
    		//字符转数字
    		if( Numbers.find(*c) != string::npos ){
    			string num;
    			while( c != formula.end()  &&   Numbers.find(*c) != string::npos ){
    				num += *c;
    				c++;
    			}
    			c--;	//退一步
    			operands.push( stod(num) );
    			//cout << operands.top() << endl;	//test
    		}
    		//运算
    		else if( Operators.find(*c) != string::npos ){
    			if( operators.empty() )	
    				operators.push(*c);
    			else{
    				//这里while很关键
    				while( !operators.empty()  &&  getPriority(operators.top()) >= getPriority(*c) ){
    					calculator( operands, operators);
    				}
    				operators.push(*c);
    			}
    		}
    		//括号处理
    		else{
    			if( *c == '(' )
    				operators.push(*c);
    			else{
    				while( operators.top() != '(' ){
    					calculator( operands, operators);
    				}
    				operators.pop();
    			}
    		}
    	}
    
    
    	while( !operators.empty() ){
    		calculator( operands, operators );
    	}
    
    	cout << formula << " = " << operands.top() << endl;
    	return 0;
    }
    
  • 相关阅读:
    P、NP及NPC问题
    latex test3
    latex test2
    test
    整体二分
    bzoj2819 nim (树上带修改查询路径异或和)
    kmp模板题
    KM的三种写法比较
    电视转播
    树状数组处理区间查询和区间修改的问题
  • 原文地址:https://www.cnblogs.com/friedCoder/p/12260630.html
Copyright © 2020-2023  润新知