原创作者:Daniel
时间:2017.10.29
地点:大连理工大学软件学院
表达式计算至少需要两个栈:1、数据栈 2、运算符栈
中缀表达式定义:
<表达式>::=<项> + <项> |<项> - <项> | <项>
项 ::= <因子> * <因子> | <因子> / <因子> | <因子>
<因子> ::= <常数> | (表达式)
<常数> ::= <数字> | <数字> <数字>
<数字> ::= 0|1|2|3|4|5|6|7|8|9
中缀表达式计算通常按照我们习惯的先乘除后加减,有括号先算括号。
逆波兰表达式定义:
<表达式>::=<项><项> + |<项> <项> - | <项>
项 ::= <因子> <因子> *| <因子> <因子>/ | <因子>
<因子> ::= <常数>
<常数> ::= <数字> | <数字> <数字>
<数字> ::= 0|1|2|3|4|5|6|7|8|9
在逆波兰表达式中,数字按照原来的顺序出现,运算放在参与运算的两个项或者因子后边
比如:
23 + (34 * 45)/(5 + 6 + 7)
23 34 45* 5 6 +7+/+
计算逆波兰表达式比中缀表达式要容易一些,具体过程如下:
1、扫描表达式,操作数入栈
2、遇到运算符,就在栈顶取出两个元素,用后取出的 操作 先取出的
3、将运算所得的数字进栈
4、循环123,直到表达式扫描完成,栈顶元素就是表达式的值
在计算中缀表达式时有两种方法:1、转化为后缀表达式 2、直接计算
1、中缀转化后缀方法:
1)定义操作数的栈内外优先级
2)扫描中缀表达式,遇到数字就输出
2)遇到运算符,就将预算符的优先级(栈外优先级)与栈顶元素比较
若栈外 高于 栈内 进栈
栈外 低于 栈内,依次弹出运算符输出,直到栈顶元素优先级小于或者等于栈外元素优先级
如果栈内外优先级相等,则栈顶元素弹出,不输出
2、直接计算和1 过程基本一致,需要在运算符出栈过程进行算术运算,同时需要管理两个栈。#include<stdio.h>
#include<stdlib.h>
#include<stack>
int priorityisp(char op) {
switch (op) {
case '#':
return 0;
break;
case '(':
return 1;
break;
case '^':
return 7;
break;
case '*':
case '/':
return 5;
break;
case '+':
case '-':
return 3;
break;
case ')':
return 8;
break;
default:
printf("error!");
break;
}
return -1;
}
int priorityicp(char op) {
switch (op)
{
case '#':
return 0;
break;
case '(':
return 8;
break;
case '^':
return 6;
break;
case '*':
case '/':
return 4;
break;
case '+':
case '-':
return 2;
break;
case ')':
return 1;
break;
default:
printf("error!");
break;
}
return -1;
}
char* changeExp(char* exp) {
char* postfixExp = (char*)malloc(sizeof(char) * 20);
std::stack<char> oper;
oper.push('#');
int i = 0;
int j = -1;
while (exp[i]) {
switch (exp[i]) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
postfixExp[++j] = exp[i];
break;
default:
while (priorityicp(exp[i]) < priorityisp(oper.top())) {
postfixExp[++j] = oper.top();
oper.pop();
}
if (priorityicp(exp[i]) > priorityisp(oper.top()))
oper.push(exp[i]);
else {
oper.pop();
}
break;
}
i++;
}
postfixExp[++j] = '\0';
return postfixExp;
}
int calculate(char* postfixExp) {
std::stack<char> cal;
int i = 0;
while (postfixExp[i]) {
switch (postfixExp[i]) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
cal.push(postfixExp[i]);
break;
default:
int num1 = cal.top() - '0';
cal.pop();
int num2 = cal.top() - '0';
cal.pop();
switch (postfixExp[i]) {
case '+':
cal.push(num2 + num1 + '0');
break;
case '-':
cal.push(num2 - num1 + '0');
break;
case '*':
cal.push(num2 * num1 + '0');
break;
case '/':
cal.push(num2 / num1 + '0');
break;
}
}
i++;
}
return cal.top() - '0';
}
int main(int argc, char** argv) {
char InfixExp[20];
char* PostfixExp;
int i = 0;
while ((InfixExp[i] = getchar()) != '\n')
i++;
InfixExp[i] = '\0';
PostfixExp = changeExp(InfixExp);
printf("%d", calculate(PostfixExp));
system("pause");
return 0;
}