给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。
给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。
输入第一行给出一个正整数N(<=30),是二叉树中结点的个数。第二行给出其后序遍历序列。第三行给出其中序遍历序列。数字间以空格分隔。
在一行中输出该树的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
4 1 6 3 5 7 2
若不存在这样的序列,则什么也不输出
假定已知二叉树如下:
___7___ / \ 10 2 / \ / 4 3 8 \ / 1 11
那么它的先序遍历和中序遍历的结果如下:
preorder = {7,10,4,3,1,2,8,11} inorder = {4,10,3,1,7,11,8,2}
需要关注的几个要点:
1)先序遍历的第一个结点总是根结点。如上图中的二叉树,根结点为7,也是先序遍历的第一个值。先序遍历时父亲结点总是在孩子结点之前遍历。
2)可以观察到在中序遍历中,7是第4个值(从0开始算起)。由于中序遍历顺序为:左子树,根结点,右子树。所以7左边的{4,10,3,1} 这四个结点属于左子树,而根结点7右边的{11,8,2}属于右子树。
3)可以从上面的结论很轻松的得到递归式。在构建了根结点7后,我们可以根据中序遍历{4, 10, 3, 1} 和{11,8,2}分别构建它的左子树和右子树。我们同时需要相应的先序遍历结果用于发现规律。我们可以由先序遍历知道左右子树的先序遍历分别是{10,4, 3, 1}和{2, 8, 11}。左右子树也分别为二叉树,由此可以递归来解决问题。
4)关于如何得到根结点在中序遍历中的位置,我们使用线性扫描查找位置,则每次查找需要O(N)的时间。需要注意的是,这里的二叉树结点值不能有相同的值。
#include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #define SizeMax 105 using namespace std; typedef struct Node { int data; Node* lchild; Node* rchild; } Node; Node *CreateBT2(int *post,int *in,int n) { Node *b; int r,*p,k; if(n<=0)return NULL; r=*(post+n-1); b=(Node*)malloc(sizeof(Node)); b->data=r; for(p=in; p<in+n; p++) if(*p==r)break; k=p-in; b->lchild=CreateBT2(post,in,k); b->rchild=CreateBT2(post+k,p+1,n-k-1); return b; } void Print(Node *r) { Node *p; Node *pr[SizeMax]; int rear=-1,front=-1; rear++; pr[rear]=r; while(rear!=front) { front=(front+1)%SizeMax; p=pr[front]; printf("%d ",p->data); if(p->lchild!=NULL) { rear=(rear+1)%SizeMax; pr[rear]=p->lchild; } if(p->rchild!=NULL) { rear=(rear+1)%SizeMax; pr[rear]=p->rchild; } } } int main() { int N; scanf("%d",&N); int a[N],b[N]; for(int i=0; i<N; i++) scanf("%d",a+i); for(int i=0; i<N; i++) scanf("%d",b+i); Node* result=CreateBT2(a,b,N); Print(result); return 0; }