我们平时写的表达式称为中缀表达式。
eg: 1. 2 - 3*4 +5 2. 2* (3- 5) +7
正如上面的表达式,我们在计算的过程中,首先要注意运算符的优先级,其次要注意括号。 我们应如何判断运算符的优先级以及如何进行运算。
首先,我们可以将中缀表达式转化为后缀表达式(逆波兰表达式),然后进行运算。如何将中缀表达式转化为后缀表达式呢?规则如下:
将上面的中缀表达式转化为后缀表达式:1. 2 3 4 * - 5 + 2. 2 3 - 5 * 7 +
借助栈,依次遍历后缀表达式,当遇到操作数时,直接进行入栈。当遇到操作符时,弹出栈中的两个元素,依次作为右操作数和左操作数,将计算后的结果压入栈中。最后栈中剩余的元素,则为表达式的值。
代码实现:
#include<iostream> #include<vector> #include<string> #include<stack> using namespace std; //判断是操作符还是操作数 enum Cal_Type { OP_NUM, OP_SYMBOL, }; struct Cell { Cal_Type _type;//计算类型 int _value; Cell(const Cal_Type& t, const int& x) :_type(t) ,_value(x) {} }; class Calculator { public: Calculator(const vector<int> &exp) :_infix(exp) {} int Count() { Transition(); //将中缀表达式转化为后缀表达式 stack<int> num; //中间计算过程中的操作数 int n = _exp.size(); for(int i=0; i<n; ++i) { Cell cur = _exp[i]; if(cur._type == OP_NUM) { num.push(cur._value); } else if(cur._type == OP_SYMBOL) { int d2 = num.top(); //右操作数 num.pop(); int d1 = num.top(); //左操作数 num.pop(); int sum = 0; switch(cur._value) { case '+': {sum = d1+d2;} break; case '-': {sum = d1-d2;} break; case '*': {sum = d1*d2;} break; case '/': {sum = d1/d2;} break; default: break; } num.push(sum); } } return num.top(); } //判断是否为操作符 bool IsTypied(char op) { switch(op) { case '-': case '+': case '*': case '/': return true; default: return false; break; } } //确定操作符的优先级 int Priority(char op) { switch(op) { case '-': case '+': return 1; case '*': case '/': return 2; default: break; } return -1; } //中缀转后缀表达式 void Transition() { stack<int> tmp; //用于保存遇到‘(’时的运算符 for(int i=0; i<_infix.size(); ++i) { if((_infix[i]+48)>='0' && (_infix[i]+48)<='9')//当遇到数字时,直接插入后缀表达式中 { Cell c(OP_NUM,_infix[i]); _exp.push_back(c); } else if(_infix[i] == '(') { tmp.push(_infix[i]); } else if(_infix[i] == ')') { while(tmp.top() != '(') { _exp.push_back(Cell(OP_SYMBOL,tmp.top())); tmp.pop(); } tmp.pop(); } else if(IsTypied(_infix[i])) //如果为运算符,应该判断优先级 { if(tmp.empty() || Priority(_infix[i]) > Priority(tmp.top()))//如果tmp为NULL的话,只需要判断栈顶元素和_infix[i]的优先级 { tmp.push(_infix[i]); } else { while(!tmp.empty() && Priority(_infix[i]) <= Priority(tmp.top())) { _exp.push_back(Cell(OP_SYMBOL,tmp.top())); tmp.pop(); } tmp.push(_infix[i]); } } else { cout<<"输入有误"<<endl; _exp.clear(); return ; } } //如果tmp 不为NULL的话,全部压入_exp中 while(!tmp.empty()) { _exp.push_back(Cell(OP_SYMBOL,tmp.top())); tmp.pop(); } } private: vector<int> _infix; //中缀表达式 vector<Cell> _exp; //后缀表达式 }; void Test() { int a[] = {2,'-',3,'*',4,'+',5}; vector<int> exp(a,a+sizeof(a)/sizeof(a[0])); Calculator c(exp); cout<<c.Count()<<endl; }