03-树2. Tree Traversals Again (25)
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 PopSample Output:
3 4 2 6 5 1
这题还是比较好的二叉树练手题,实际上Push序列就是前序遍历,而依次Pop出的就是中序遍历。由这两个遍历就可以构建二叉树。而后对二叉树后序遍历。就得到了要求的输出
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct bintree{
int data;
struct bintree* Left;
struct bintree* right;
}BinTree;
int input(void);
void PostOrderTraversal(BinTree* p);
BinTree* CreateBinTree(int* Pre,int* In,int Len);
int main(){
int n,i;
scanf("%d",&n);
int command[2*n];
int K = 0,front[n*10],mid[n*10],k = 0,after[n*10];
int stack[n*10],top = 0;
// 记录操作流 构建前序列
for(i = 0;i<2*n;i++){
command[i] = input();
if(command[i] != -1){
front[K] = command[i];
K++;
}
}
// 构建中序列
for(i = 0;i<2*n;i++){
if(command[i] != -1){
stack[top] = command[i];
top++;
}else{
mid[k] = stack[--top];
k++;
}
}
// 1.构建二叉树,2.对二叉树后序遍历
PostOrderTraversal(CreateBinTree(front,mid,n));
return 0;
}
void PostOrderTraversal(BinTree* p){
static int t = 0;
if(p!=NULL){
PostOrderTraversal(p->Left);
PostOrderTraversal(p->right);
if(0 == t){
printf("%d",p->data);
t = 1;
}
else
printf(" %d",p->data);
}
}
BinTree* CreateBinTree(int* Pre,int* In,int Len){
BinTree* T;
int i;
if(!Len)
return NULL;
T = (BinTree*)malloc(sizeof(BinTree));
T->data = Pre[0];
for(i = 0;i<Len;i++)
if(Pre[0] == In[i])
break;
T->Left = CreateBinTree(Pre+1,In,i);
T->right = CreateBinTree(Pre+i+1,In+i+1,Len-i-1);
return T;
}
int input(void){
char a[20],b[20] = "Push",c[20] = "Pop";
int t;
scanf("%s",a);
if(!strcmp(a,b)){
scanf("%d",&t);
return t;
}
if(!strcmp(a,c))
return -1;
}
而陈越老师这里用了一个更巧的方法,就是用分治法直接由前序遍历和中序遍历得出后序遍历。算法实现如下(只取后序构建算法)
void solve(int* pre,int* in,int* post,int preL,int inL,int postL,int n){
int root;
if(0 == n)
return ;
if(1 == n){
post[postL] = pre[preL];
return ;
}
root = pre[preL];
post[postL+n-1] = root;
int i;
for(i = 0;i<n;i++)
if(in[inL+i] == root)
break;
solve(pre,in,post,preL+1,inL,postL,i);
solve(pre,in,post,preL+i+1,inL+i+1,postL+i,n-i-1);
}