An inorder binary tree traversal can be implemented in a non-recursive way with a stack. For example, suppose that when a 6-node binary tree (with the keys numbered from 1 to 6) is traversed, the stack operations are: push(1); push(2); push(3); pop(); pop(); push(4); pop(); pop(); push(5); push(6); pop(); pop(). Then a unique binary tree (shown in Figure 1) can be generated from this sequence of operations. Your task is to give the postorder traversal sequence of this tree.
Figure 1
Input Specification:
Each input file contains one test case. For each case, the first line contains a positive integer N (≤30) which is the total number of nodes in a tree (and hence the nodes are numbered from 1 to N). Then 2N lines follow, each describes a stack operation in the format: "Push X" where X is the index of the node being pushed onto the stack; or "Pop" meaning to pop one node from the stack.
Output Specification:
For each test case, print the postorder traversal sequence of the corresponding tree in one line. A solution is guaranteed to exist. All the numbers must be separated by exactly one space, and there must be no extra space at the end of the line.
Sample Input:
6
Push 1
Push 2
Push 3
Pop
Pop
Push 4
Pop
Pop
Push 5
Push 6
Pop
Pop
Sample Output:
3 4 2 6 5 1
个人分析:??怎么又要遍历树了,emmmmmm。题目给出了目标树中序堆栈遍历的出入栈顺序,要求据此得出目标树的后序遍历顺序并输出,输出老套路,前面各个数都要用空格隔开,最后不能有空格。菜鸡第一想法:根据输入建树,然后写一个后序遍历输出即可。
又是一句这么简单的分析.....现在看越清晰的题目越害怕,弯弯绕不一定就少。
“根据输入建树”这就是第一个弯了,一般来说,可以根据树的前中后序遍历中的二者,求出第三者。然后,题目好像只告诉我们了中序遍历顺序,还信誓旦旦的告诉我们,一定能得出唯一的后序遍历顺序......真是woc啊.....当然,不可能是题目错了,只能是菜鸡还没发现诀窍。
再仔细想想,题目好像确实给了俩个数字序列:push序列+pop序列。有 、意思!emmmm,用样例看看是不是能从这俩个序列里唯一确定一棵树,如图:
原来真的可以唯一确定一棵树,想想也应该,因为输入确实“唯一的”遍历了树,不可能有两棵不同的树有同种中序遍历顺序。
问题到这里,本来已经可以写出满足测试的代码了。但是,陈越姥姥曾给我们一个思路:是不是一定要建树?
是否仅仅根据这两行序列,就能直接得到后序遍历的输出?emmmmmm其实确实可以,但是菜鸡当时没那么聪明,还是建树了,再者还想练一下建树的代码。
代码如下:
#include<stdio.h> #include<stdlib.h> #define Maxsize 30 int tag=0; //改变输出格式 //链式堆栈结构体声明 typedef struct StackNode* Link; struct StackNode{ int data; Link next; }; //链式树结构体声明 typedef struct TreeNode* BinTree; struct TreeNode{ int data; BinTree left; BinTree right; }; //创建树头结点 BinTree CreateTree(int X) { BinTree T=(BinTree)malloc(sizeof(TreeNode)); T->data=X; T->left=NULL; T->right=NULL; return T; } //建树函数 BinTree BuildTree(int s1[],int s2[],int head,int end,int size,BinTree T,int position) //head与end标注当前结点左右儿子在出栈序列中的取值范围 { int limit; //limit当前结点在出栈序列中的位置,position当前结点在入栈序列中的位置 for(int i=0;i<size;i++) { if(T->data==s2[i]) { limit=i; break; } } if(limit>head+1) //表明当前结点有左儿子 { BinTree tl=(BinTree)malloc(sizeof(TreeNode)); tl->data=s1[position+1]; tl->left=NULL; tl->right=NULL; T->left=tl; BuildTree(s1,s2,head,limit,size,tl,position+1); } if(limit<end-1) //表明当前结点有右儿子 { BinTree tr=(BinTree)malloc(sizeof(TreeNode)); tr->data=s1[position+(limit-head)]; tr->left=NULL; tr->right=NULL; T->right=tr; BuildTree(s1,s2,limit,end,size,tr,position+limit-head); } return T; } //堆栈初始化头结点函数 Link CreateStack() { Link P=(Link)malloc(sizeof(StackNode)); P->next=NULL; return P; } //堆栈判空函数 bool IsEmpty(Link T) { if(T->next==NULL) return false; else return true; } //堆栈入栈函数 Link Push(Link T, int X) { Link rear=(Link)malloc(sizeof(StackNode)); rear->data=X; rear->next=T->next; T->next=rear; return T; } //堆栈出栈函数 int Pop(Link T) { if(IsEmpty) { Link Topitem; int Data; Topitem=T->next; T->next=Topitem->next; Data=Topitem->data; free(Topitem); return Data; } else { printf("栈空\n"); return 0; } } //树后序遍历函数 void PostOrderTravel(BinTree q) { if(q){ PostOrderTravel(q->left); PostOrderTravel(q->right); if(tag==0) { printf("%d",q->data); tag=1; } else { printf(" %d",q->data); } } } int main() { //建立堆栈,根据输入,得到入出栈序列 int size,number,rear1,rear2; rear1=rear2=0; Link Top; char a[4]; int s1[Maxsize];//记录入栈序列 int s2[Maxsize];//记录出栈序列 Top=CreateStack(); scanf("%d",&size); getchar(); for(int i=0;i<2*size;i++) { scanf("%s",&a); if(a[1]=='u') { scanf("%d",&number); getchar(); Push(Top,number); s1[rear1]=number; rear1+=1; } else if(a[1]=='o') { getchar(); s2[rear2]=Pop(Top); rear2+=1; } } //根据入出栈序列构造树 BinTree T=CreateTree(s1[0]); BinTree Q=BuildTree(s1,s2,-1,size,size,T,0); //树的后序遍历 int tag=0; PostOrderTravel(Q); }
测试结果:
总结:苏服啊苏服,还是要去学习一下怎么直接得出后序输出,感觉数学学的更好一点,写的代码能更美更简洁!