这题想了挺长时间,刚开始用了3个栈,很复杂,最后也过了,想了想改成了两个栈,简单了许多。题目如下:
逆波兰表达式,就是抽成又向无环图的后续遍历,其中符号的优先级比较难处理,情况很多。
我的实现如下:
#include <stdio.h> #include <stdlib.h> struct charStack { union { char data[300]; int pos[300]; }; int top; }; struct orientedGraphNode { char data; int left; int right; }; struct orientedGraph { struct orientedGraphNode L[300]; int n; }; void run(); void putInDatas(); void getRPNGraph(); int typeJudge(char c); void pushBack(int pos); int createNewNode(); int findLetterPosition(char c); int findSymbolPosition(char c, int left,int right); void pushSymbolStack(struct charStack *S, char c); void pushPositionStack(struct charStack *S, int position); void popStack(struct charStack *S); void putOut(); void postorderTraversal(int n); struct orientedGraph gList; struct charStack lStack, sStack; char s[300]; int len; int main() { run(); return 0; } void run() { putInDatas(); getRPNGraph(); putOut(); } void putInDatas() { char c; len = -1; while((c = getchar()) != '\n') { len++; s[len] = c; } } void getRPNGraph() { int i, pos; for(i = 0; i <= len; i++) { switch(typeJudge(s[i])) { case 0 : { pushBack(findLetterPosition(s[i])); break; } case 1 : { if(sStack.top >= 0 && (sStack.data[sStack.top] == '+' || sStack.data[sStack.top] == '-')) { pos = createNewNode(); pushBack(pos); } pushSymbolStack(&sStack, s[i]); break; } case 2 : { pushSymbolStack(&sStack, s[i]); break; } case 3 : { if (sStack.data[sStack.top] != '(') { pos = createNewNode(); popStack(&sStack); pushBack(pos); } else { popStack(&sStack); } } } } if (sStack.top >= 0) createNewNode(); } int typeJudge(char c) { if (c >= 'a' && c <= 'z') return 0; if (c == '+' || c == '-') return 1; if (c == '*' || c == '/' || c == '(') return 2; if (c == ')') return 3; return -1; } void pushBack(int pos) { pushPositionStack(&lStack, pos); if(sStack.top >= 0 && (sStack.data[sStack.top] == '*' || sStack.data[sStack.top] == '/')) { pos = createNewNode(); pushBack(pos); } } int createNewNode() { int pos; if(!(pos = findSymbolPosition(sStack.data[sStack.top], lStack.data[lStack.top - 1], lStack.data[lStack.top]))) { pos = ++(gList.n); gList.L[gList.n].data = sStack.data[sStack.top]; gList.L[gList.n].left = lStack.pos[lStack.top - 1]; gList.L[gList.n].right = lStack.pos[lStack.top]; } popStack(&sStack); popStack(&lStack); popStack(&lStack); return pos; } int findLetterPosition(char c) { int i; for(i = 1; i <= gList.n; i++) { if(c == gList.L[i].data) return i; } gList.L[++(gList.n)].data = c; return gList.n; } int findSymbolPosition(char c, int left,int right) { int i; for(i = 1; i <= gList.n; i++) { if(c == gList.L[i].data && left == gList.L[i].left && right == gList.L[i].right) return i; } return 0; } void pushSymbolStack(struct charStack *S, char c) { S->data[++(S->top)] = c; } void pushPositionStack(struct charStack *S, int position) { S->pos[++(S->top)] = position; } void popStack(struct charStack *S) { --(S->top); } void putOut() { postorderTraversal(gList.n); printf("\n"); } void postorderTraversal(int n) { if (gList.L[n].left) postorderTraversal(gList.L[n].left); if (gList.L[n].right) postorderTraversal(gList.L[n].right); printf("%c", gList.L[n].data); }
各函数的注释如下:
void run() { putInDatas();//输入数据 getRPNGraph();//键图 putOut();//输出 }
void putInDatas() { char c; len = -1; while((c = getchar()) != '\n')//遍历输入 { len++; s[len] = c; } }
void getRPNGraph() { int i, pos; for(i = 0; i <= len; i++)//遍历 { switch(typeJudge(s[i])) { case 0 ://字母 { pushBack(findLetterPosition(s[i]));//再入栈 break; } case 1 ://+- { if(sStack.top >= 0 && (sStack.data[sStack.top] == '+' || sStack.data[sStack.top] == '-'))//若前一个符号是+- { pos = createNewNode();//就用前一个符号构建 pushBack(pos);//再入栈 } pushSymbolStack(&sStack, s[i]);//符号入栈 break; } case 2 ://*/() { pushSymbolStack(&sStack, s[i]);//符号入栈 break; } case 3 ://) { if (sStack.data[sStack.top] != '(')//若上一个不是( { pos = createNewNode();//根据括号里建图 popStack(&sStack);//(出栈 pushBack(pos);//再入栈 } else//若上一个是(,说明为(x)格式,括号无用 { popStack(&sStack);//(出栈 } } } } if (sStack.top >= 0) createNewNode();//若还有一步运算,建图 }
int typeJudge(char c) { if (c >= 'a' && c <= 'z') return 0;//转换 if (c == '+' || c == '-') return 1; if (c == '*' || c == '/' || c == '(') return 2; if (c == ')') return 3; return -1; }
void pushBack(int pos) { pushPositionStack(&lStack, pos);//字母位置入栈 if(sStack.top >= 0 && (sStack.data[sStack.top] == '*' || sStack.data[sStack.top] == '/'))//若前面是*/ { pos = createNewNode();//据*/建图 pushBack(pos);//再入栈 } }
int createNewNode() { int pos; if(!(pos = findSymbolPosition(sStack.data[sStack.top], lStack.data[lStack.top - 1], lStack.data[lStack.top])))//若无找到已有操作 { pos = ++(gList.n);//创建新节点,赋值 gList.L[gList.n].data = sStack.data[sStack.top]; gList.L[gList.n].left = lStack.pos[lStack.top - 1]; gList.L[gList.n].right = lStack.pos[lStack.top]; } popStack(&sStack);//出栈 popStack(&lStack); popStack(&lStack); return pos;//返回位置 }
int findLetterPosition(char c) { int i; for(i = 1; i <= gList.n; i++)//遍历寻找 { if(c == gList.L[i].data) return i; } gList.L[++(gList.n)].data = c; return gList.n; } int findSymbolPosition(char c, int left,int right) { int i; for(i = 1; i <= gList.n; i++)//遍历寻找 { if(c == gList.L[i].data && left == gList.L[i].left && right == gList.L[i].right) return i; } return 0; }
//栈操作 void pushSymbolStack(struct charStack *S, char c) { S->data[++(S->top)] = c; } void pushPositionStack(struct charStack *S, int position) { S->pos[++(S->top)] = position; } void popStack(struct charStack *S) { --(S->top); }
//后序输出 void putOut() { postorderTraversal(gList.n); printf("\n"); } void postorderTraversal(int n) { if (gList.L[n].left) postorderTraversal(gList.L[n].left); if (gList.L[n].right) postorderTraversal(gList.L[n].right); printf("%c", gList.L[n].data); }以上就是我的实现。感觉这次写的很垃圾,思路不太清晰,比较繁琐。。。