这题想了挺长时间,刚开始用了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);
}
以上就是我的实现。感觉这次写的很垃圾,思路不太清晰,比较繁琐。。。