算法要点:
1) 采用双栈,一个栈用来保存运算符,一个栈用来保存数据
2) 符号优先级设置
i(+ -)< (* /)
ii 相同运算符,栈内优先级高于栈外优先级
ii 对于栈内:左括号的优先级最高 右括号优先级仅高于'#'
ii 对于栈外:与上面相反
3)计算时机
当栈内运算符优先级 > 栈外运算符优先级:可以计算,计算结果压入数据栈
当栈内运算符优先级 < 栈外运算符优先级:栈外运算符压入运算符栈
当栈内运算符优先级 = 栈外运算符优先级:只可能是左括号和右括号的情况,将左括号
出栈即可
算法理解建议:
输入一个简单的表达式,最好包含括号的情况,然后单步调试,跟踪两个栈的数据变化情况
算法实现(包括测试代码):
- /************************************************************************/
- /* 表达式 求值 */
- /************************************************************************/
- #include <iostream>
- #include <stack>
- using namespace std;
- //符号数组
- char symbol[7] = {'+', '-', '*', '/', '(', ')', '#'};
- //栈内元素的优先级
- int in[7] = {3, 3, 5, 5, 1, 6, 0};
- //栈外元素的优先级
- int out[7] = {2, 2, 4, 4, 6, 1, 0};
- /*
- * 通过符号字符获取它的数组下标
- */
- int get(char c)
- {
- switch(c)
- {
- case '+':
- return 0;
- case '-':
- return 1;
- case '*':
- return 2;
- case '/':
- return 3;
- case '(':
- return 4;
- case ')':
- return 5;
- case '#':
- return 6;
- default:
- return 6;
- }
- }
- /*
- * 比较栈内运算符c1和栈外运算符c2的优先级
- */
- char precede(char c1, char c2)
- {
- int i1 = get(c1);
- int i2 = get(c2);
- if(in[i1] > out[i2])
- {
- return '>';
- }
- else if(in[i1] < out[i2])
- {
- return '<';
- }
- else
- {
- return '=';
- }
- }
- /*
- * 计算基本表达式的值
- */
- int figure(int a, int theta, int b)
- {
- switch(theta)
- {
- case 0:
- return a + b;
- case 1:
- return a - b;
- case 2:
- return a * b;
- default:
- return a / b;
- }
- }
- /*
- * 计算表达式的值
- */
- int EvaluateExpression(const char *exp)
- {
- stack<int> data; //数据栈
- stack<int> oper; //符号栈
- oper.push(get('#'));
- int sum = 0;
- int flag = 1; //表示正负号 1,表示正 0,表示负
- int a, theta, b;
- if(!('+' == *exp || '-' == *exp || '(' == *exp || isdigit(*exp)))
- {
- cout << "表达式出错1" << endl;
- return -1;
- }
- if('-' == *exp)
- {
- flag = 0;
- exp++;//指向下一个字符
- }
- int index = oper.top();
- while(*exp || symbol[index] != '#')
- {
- if(isdigit(*exp))
- {
- sum = 0;
- if(flag)
- {
- while(isdigit(*exp))
- {
- sum = sum * 10 + *exp - '0';
- exp++;
- }
- }
- else
- {
- while(isdigit(*exp))
- {
- sum = sum * 10 - *exp - '0';
- exp++;
- }
- }
- data.push(sum);
- flag = 1;
- }
- else
- {
- switch(precede(symbol[oper.top()], *exp))
- {
- case '>' :
- b = data.top();
- data.pop();
- a = data.top();
- data.pop();
- theta = oper.top();
- oper.pop();
- data.push(figure(a, theta, b));
- break;
- case '<' :
- oper.push(get(*exp));
- if(*exp)
- {
- exp++;
- }
- break;
- case '=' :
- oper.pop();
- if(*exp)
- {
- exp++;
- }
- break;
- }
- }
- index = oper.top();
- }
- return data.top();
- }
- int main()
- {
- cout << EvaluateExpression("((8+6)*2-8)/2") << endl;
- system("pause");
- return 0;
- }