Expressions
题目链接:http://acm.bnu.edu.cn/bnuoj/problem_show.php?pid=14332
题目大意:
一个表达式,可以用栈来处理,同时可以用队列来处理。现在告诉你用栈处理的表达式顺序,求其用队列表示的顺序? 几种操作数为小写字母,操作符为大写字母。
如输入:
2 xyPzwIM abcABdefgCDEF则输出:
wzyxIPM gfCecbDdAaEBF
解题思路:
我们知道表达式在计算机中可以用二叉树表示。其中正常的表达式为树的中序遍历,而采用栈来模拟,则为树的后序遍历。如果用队列来表示表达式呢?
我们不妨把第一组样例的表达式处理成二叉树,然后对比队列的输出,便一目了然了。
我们可以看到,用栈表示为其后序,而用队列表示是其层次遍历的逆序输出。层次为MPIxyzw。
所以这道题就变成了先建树,然后再层次遍历,最后逆序输出。
我一开始的做法是,利用栈的后序,可以得到其中序遍历,然后利用中序和后序可以建树。但是由于这个树比较深,所以会爆栈。
其实利用栈的后序,完全可以直接建树了,因为操作符和操作数分别是大小写字母,可以区分。
即遇到小写字母就建立一个只有根节点的树,并将该地址入栈。
遇到大写字母,就建立一个根节点为该大写字母,然后从栈中取出两个地址,分别作为该节点的左右孩子,然后再将该根节点地址入栈
由于怕栈溢出,所有的栈操作都改为了数组模拟。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<string> #include<stack> #include<algorithm> using namespace std; char post[10010]; struct tree { char ch; tree* lchild; tree* rchild; }; tree* newnode() { tree* u = (tree*) new (tree); u->ch = ‘\0‘; u->lchild = u->rchild = NULL; return u; } void bfs(tree* root) { char out[10010]; tree* que[10010] = {NULL}; int font, rear, k = 0; font = 0, rear = 1; que[font] = root; out[k++] = root->ch; while(font < rear) { tree* tmp; tree* next; tmp = que[font++]; if (tmp->lchild != NULL) { next = tmp->lchild; que[rear++] = next; out[k++] = next->ch; } if (tmp->rchild != NULL) { next = tmp->rchild; que[rear++] = next; out[k++] = next->ch; } } for (int i = k - 1; i >= 0; i--) cout<<out[i]; } int main () { int t, i, n; cin>>t; getchar(); while(t--) { gets(post); n = strlen(post); tree* s[10010]; int k = 0; for (i = 0; i < n; i++) { if (post[i] <= ‘Z‘) //碰到操作符,从栈中取出两个地址,分别作为左右孩子,然后将其根地址再次入栈 { tree* u = newnode(); u->ch = post[i]; u->rchild = s[--k]; u->lchild = s[--k]; s[k++] = u; } else //碰到操作数,将地址其入栈 { tree* u = newnode(); u->ch = post[i]; s[k++] = u; } } tree* root = s[--k]; //把树的根节点取出 bfs(root); //进行层次遍历 puts(""); memset(post, 0, sizeof(post)); } return 0; }