数据结构:用栈求中缀表达式的值
一、思路:
-
定义两个栈:s1和s2,其中s1为操作数栈,用来存放操作数,s2为运算符栈,用来存放运算符。
-
定义一个操作(在下文中称为“运算操作”):从操作数栈s1中依次连续出栈两个操作数,第一个操作数在右,第二个操作数在左,再从运算符栈s2中出栈一个运算符放到两个操作数中间。最后将运算结果压入操作数栈s1中。
-
从左往右扫描中缀表达式:
①如果碰到操作数,则直接将其压入操作数栈s1中。
②如果碰到运算符:
a·若运算符栈s2为空 或 运算符栈s2栈顶元素为左括号’(’ 或 当前运算符为左括号’(’,则直接将其压入运算符栈s2中。
b·若当前运算符为右括号’)’,则循环执行“运算操作”,直至碰到左括号’(’,最后再将左括号’('出栈。
c·若当前运算符不为上述两种情况,且不为括号。若当前运算符的优先级大于(>)运算符栈s2栈顶元素的优先级,则直接将当前运算符入栈;若当前运算符的优先级小于或等于(<=)运算符栈s2栈顶元素的优先级,则执行一次“运算操作”。 -
若运算符栈s2不为空,则一直执行“运算操作”,直至s2为空。
-
此时操作数栈s1的栈顶元素即为所求答案
二、C++ 代码
#include<iostream>
using namespace std;
const int maxSize = 1000;
//获取当前运算符的优先级
int getPriority(char Op)
{
if(Op == '+' || Op == '-')
return 0;
else
return 1; //这样保证了乘和除的优先级大于加和减的优先级
}
//两个操作数和一个运算符进行运算
int op(int a, char Op, int b)
{
if(Op == '+') return a + b;
else if(Op == '-') return a - b;
else if(Op == '*') return a * b;
else
{
if(b == 0) //注意除数不能为零,要特判
{
cout << "ERROR : 除数为零!" << endl;
return -1;
}
else
return a / b;
}
}
//"运算操作":从操作数栈s1中弹出两个元素,第一个在右,第二个在左,运算符栈s2中弹出一个运算符
// 三者进行op操作,最后将结果压入操作数栈s1中
int act(int s1[], int &top1, char s2[], int &top2)
{
int a, b, c;
char Op;
b = s1[top1 --];
a = s1[top1 --];
Op = s2[top2 --];
c = op(a, Op, b);
s1[++ top1] = c;
return c;
}
int com(char exp[])
{
int s1[maxSize], top1 = -1; //定义操作数栈s1(整形),并初始化
char s2[maxSize]; int top2 = -1; //定义运算符栈s2(字符型),并初始化
for(int i = 0; exp[i] != '\0'; i ++) //从左向右遍历exp[]数组
{
if(exp[i] >= '0' && exp[i] <= '9') //碰到数字
s1[++ top1] = exp[i] - '0'; //转化成整形后压入操作数栈s1中
else
{
if(
top2 == -1 || //运算符栈s2为空
exp[i] == '(' || //遇到左括号
s2[top2] == '(' || //运算符栈顶为左括号
(exp[i] != '(' && exp[i] != ')' && getPriority(exp[i]) > getPriority(s2[top2]))
//当前运算符不为括号并且优先级大于(>)s2栈顶元素优先级
)
s2[++ top2] = exp[i]; //以上四种情况直接将运算符压入运算符栈s2中
else if(exp[i] == ')') //遇到右括号
{
while(s2[top2] != '(')
act(s1, top1, s2, top2); //循环进行上面定义的"运算操作",直到碰到左括号。注:两个括号一定是匹配的
top2 --; //将左括号出栈,不用管它
}
else if(getPriority(exp[i]) <= getPriority(s2[top2])) //当前运算符不为括号并且优先级小于或等于(<=)s2栈顶元素优先级
{
act(s1, top1, s2, top2); //先执行一次"运算操作" ,将前面优先级高的部分进行计算
s2[++ top2] = exp[i]; //再将当前运算符压入运算符栈s2中(易漏)
}
}
}
while(top2 != -1) //如果运算符栈s2不空
act(s1, top1, s2, top2); //将运算符栈s2中剩下的运算符全部进行计算
return s1[top1]; //最后操作数栈s1的栈顶元素即为所求答案
}
int main()
{
//示例:(1+2)*5+(3*6-2)*2
char exp[20];
for(int i = 0; i < 17; i ++) cin >> exp[i];
exp[17] = '\0';
cout << com(exp) << endl;
return 0;
}
代码运行结果