Tip
读者朋友你好,本篇文章的理论部分放在我的上一篇文章啦。
优化方法
上一篇文章中使用了队列,但是这多了一部分的内存开销,这篇文章我们将对上一篇文章的代码进行优化,使用两个栈(操作数栈和操作符栈)实现表达式求值。
唯一的不同在于,上一篇文章中操作符出栈是加入后缀表达式队列,但是在这次的代码实现中,操作符出栈,就会弹出操作数栈中的两个数进行运算结果再压回操作数栈,最后的操作数栈中剩余的将是运算结果。
Demo
#include <iostream>
#include <string>
using namespace std;
typedef struct NumNode {//操作数栈节点
double data;
NumNode *next;
} NumNode, *NumStack;
bool InitNumStack(NumStack &NS) {//初始化操作数占
NumNode *s;
s = (NumNode *) malloc(sizeof(NumNode));
if (s == NULL)
return false;
s->next = NULL;
NS = s;
return true;
}
bool NumStackEmpty(NumStack &NS) {//操作数栈判空
return NS->next == NULL;
}
bool NumPush(NumStack &NS, double num) {//操作数栈压栈
NumNode *p;
p = (NumNode *) malloc(sizeof(NumNode));
if (p == NULL)
return false;
p->data = num;
p->next = NS->next;
NS->next = p;
return true;
}
bool NumPop(NumStack &NS, double &num) {//操作数栈弹栈
if (NumStackEmpty(NS))
return false;
NumNode *p;
p = NS->next;
num = p->data;
NS->next = p->next;
free(p);
return true;
}
typedef struct OpNode {//操作符栈节点
char data;
OpNode *next;
} OpNode, *OpStack;
bool InitOpStack(OpStack &O) {//初始化操作符栈
OpNode *s;
s = (OpNode *) malloc(sizeof(OpNode));
if (s == NULL)
return false;
s->next = NULL;
O = s;
return true;
}
bool OpStackEmpty(OpStack O) {//操作符栈判空
return O->next == NULL;
}
bool OpPush(OpStack &O, char op) {//操作符栈压栈
OpNode *p;
p = (OpNode *) malloc(sizeof(OpNode));
if (p == NULL)
return false;
p->data = op;
p->next = O->next;
O->next = p;
return true;
}
bool OpPop(OpStack &O, char &elem) {//操作符栈弹栈
if (OpStackEmpty(O))
return false;
OpNode *p;
p = O->next;
elem = p->data;
O->next = p->next;
free(p);
return true;
}
bool OpGetTop(OpStack &O, char &elem) {//获取操作符栈顶部操作符
if (OpStackEmpty(O))
return false;
OpNode *p;
p = O->next;
elem = p->data;
return true;
}
char OpGetTopJudgment(OpStack &O) {//获取操作符栈顶部元素
if (OpStackEmpty(O))
return false;
OpNode *p;
p = O->next;
char elem;
elem = p->data;
return elem;
}
bool RankNotLowerthanOp(OpStack &O, char &op) {//获操作符等级如果大于操作符站内元素
char optop;
OpGetTop(O, optop);
cout << "********" << endl;
cout << "@@@@" << op << "@@@" << optop << endl;
if (optop == '(') {
cout << "遇到未闭合(等待)的出现" << op << "入栈" << endl;
return false;
} else if (OpStackEmpty(O)) {
cout << "操作栈空" << op << "入栈" << endl;
return false;
} else if (optop == '*' && op == '+') {
cout << "当前为+栈顶为*出栈并入队" << endl;
return true;
} else if (optop == '/' && op == '+') {
cout << "当前为+栈顶为/出栈并入队" << endl;
return true;
} else if (optop == '-' && op == '+') {
cout << "当前为+栈顶为-出栈并入队" << endl;
return true;
} else if (optop == '*' && op == '-') {
cout << "当前为-栈顶为*出栈并入队" << endl;
return true;
} else if (optop == '/' && op == '-') {
cout << "当前为-栈顶为/出栈并入队" << endl;
return true;
} else if (optop == '+' && op == '-') {
cout << "当前为-栈顶为+出栈并入队" << endl;
return true;
} else if (optop == '*' && op == '*') {
cout << "当前为*栈顶为*出栈并入队" << endl;
return true;
} else if (optop == '/' && op == '*') {
cout << "当前为/栈顶为/出栈并入队" << endl;
return true;
} else if (optop == '*' && op == '/') {
cout << "当前为/栈顶为*出栈并入队" << endl;
return true;
} else {
cout << "当前为/栈顶为/出栈并入队" << endl;
return optop == '/' && op == '/';
}
}
void countNum(string str, int length) {//计算过程
NumStack N;
InitNumStack(N);
OpStack O;
InitOpStack(O);
for (int i = 0; i < length; i++) {
if (48 <= (int) str[i] && (int) str[i] <= 57) {
cout << "读到" << (int) str[i] - 48 << "入操作数栈" << endl;
int num;
num = (int) str[i] - 48;
NumPush(N, num);
} else if (str[i] == '(') {
cout << "读到(" << "入栈" << endl;
OpPush(O, str[i]);
} else if (str[i] == ')') {
cout << "读到)" << endl;
while (!OpStackEmpty(O)) {
char op;
OpPop(O, op);
cout << "$$$$" << op << "$$$$$$" << endl;
if (op == '(') {
cout << "弹出并抛弃栈中(" << endl;
break;
}
cout << ")前" << op << "出栈并计算数栈顶两个数字" << endl;
double a, b, c;
NumPop(N, b);
NumPop(N, a);
if (op == '+') {
c = a + b;
} else if (op == '-') {
c = a - b;
} else if (op == '*') {
c = a * b;
} else {
c = a / b;
}
NumPush(N, c);
}
} else if (str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/') {
if (str[i] == '+') {
cout << "读到+" << endl;
} else if (str[i] == '-') {
cout << "读到-" << endl;
} else if (str[i] == '*') {
cout << "读到*" << endl;
} else if (str[i] == '/') {
cout << "读到/" << endl;
}
while (RankNotLowerthanOp(O, str[i])) {
char op;
OpPop(O, op);
cout << "比" << str[i] << "优先级高的" << op << "出栈并计算数栈顶两个数字" << endl;
double a, b, c;
NumPop(N, b);
NumPop(N, a);
if (op == '+') {
c = a + b;
} else if (op == '-') {
c = a - b;
} else if (op == '*') {
c = a * b;
} else {
c = a / b;
}
NumPush(N, c);
}
OpPush(O, str[i]);
}
}
while (!OpStackEmpty(O)) {
char op;
OpPop(O, op);
double a, b, c;
NumPop(N, b);
NumPop(N, a);
if (op == '+') {
c = a + b;
} else if (op == '-') {
c = a - b;
} else if (op == '*') {
c = a * b;
} else {
c = a / b;
}
NumPush(N, c);
}
double resule;
NumPop(N, resule);
cout << "结果为" << resule << endl;
}
int main() {
string str;
cin >> str;
int length = str.size();
countNum(str, length);
return 0;
}
运行结果