这两天一直在敲这个算法的代码,途中出栈的地方出了一个bug,不会用VS的断点调试,只能慢慢找,最后中途解决了问题。
本文利用了一个数组用作栈,实现中缀表达式(nifix expression)到后缀表达式(postfix expression)的转换。
算法思想如下:
- 1从左到右扫描中缀表达式
- 2遇到数字,加入后缀表达式
- 3遇到运算符:
- 3.1若是“(”,入栈
- 3.2若是“)”,依次把栈中的运算符加入后缀表达式,直到出现“(“
- 3.3若为除括号外的其他运算符:
- a 当优先级高于除“(”外的栈顶运算符时,入栈
- b 否则,从栈顶开始,依次弹出>=当前处理的运算符优先级的运算符,
- 直到一个比它优先级低的或遇到了一个左括号为止,并将元素入栈。
- 4循环第3步直到扫描元素为空
- 5将栈中剩余元素出栈
具体代码如下,除了主要算法的函数ExpTrans_nifix_to_postfix以外,还写了很多辅助函数,包括出栈pop,入栈push,给一个操作符返回优先级rank_elem等函数。
#include<iostream>
using namespace std;
#include<string>
#define MAX 100 //表达式最大长度
#define STACK_DEEPTH 20
//本项目:利用栈,将中缀表达式转换成后缀表达式
string ExpTrans_nifix_to_postfix(char s[]);
//用一个数组定义栈
struct stack {
char arr[STACK_DEEPTH];
int top =0;//top指向栈顶元素上方一格
};
//入栈函数
bool push(stack &s,char c) {
if (s.top == STACK_DEEPTH) return false;
s.arr[s.top++] = c;
return true;
}
//出栈函数
char pop(stack &s) {
if (s.top == 0)return '&';//选一个不常用的字符作为队空时的返回值
return s.arr[--s.top];
}
//独取栈顶元素
char gettop(stack &s) {
if(s.top>0)return s.arr[s.top - 1];
else {
return'&';
}
}
//从栈底输出所有元素
void printstack(stack &s) {
for(int i = 0; i < s.top; i++) {
cout << s.arr[i] << " " ;
}
cout << endl;
}
//给各种元素返回一个优先级
//字母:0 (+ - ) 1 (* /) 2 '( '100 ')'101
int rank_elem(char c) {
if ((c > 64 && c < 91)||(c>96&&c<123))return 0;
else if(c=='+'||c=='-') {
return 1;
}
else if (c == '*' || c == '/') {
return 2;
}
else if (c == '(' ) {
return 100;
}
else if (c == ')') {
return 101;
}
else {
return -1;
}
}
int main() {
char s[MAX];
cout << "***** 中缀表达式 to 后缀表达式 *****\n" << endl;
cout << "请输入中缀表达式:" << endl;
cin >> s;
cout << "后缀表达式为:\n" << ExpTrans_nifix_to_postfix(s) <<endl;
system("pause");
return 0;
}
string ExpTrans_nifix_to_postfix(char s[]) {
string postExp ;//最终要返回的后缀表达式
stack st;
for (int i = 0; i < strlen(s); i++) {
switch (rank_elem(s[i])) {
case 0://字母
postExp += s[i];
break;
case 100:
push(st, s[i]);
break;
case 101: {//如果扫描字符是右括号的情况
while (true) {
if (gettop(st) == '(') {
pop(st);
break;//直到遇到左括号停止
}
postExp += pop(st);
}
break;
}
default: {
//优先级高入栈
if (gettop(st) == '(' || rank_elem(s[i]) > rank_elem(gettop(st))) {
push(st, s[i]);
}
else {
while (true) {
if (gettop(st) == '(') {
//pop(st);
break;
}
if (rank_elem(gettop(st)) < rank_elem(s[i])) {
break;
}
postExp += pop(st);
}
push(st, s[i]);
}
break;
}
}
}
//扫描完成,将站内元素清空
while (st.top != 0) {
postExp += pop(st);
}
return postExp;
}