1020. Tree Traversals (25)
Suppose that all the keys in a binary tree are distinct positive integers. Given the postorder and inorder traversal sequences, you are supposed to output the level order traversal sequence of the corresponding binary tree.
Input Specification:
Each input file contains one test case. For each case, the first line gives a positive integer N (<=30), the total number of nodes in the binary tree. The second line gives the postorder sequence and the third line gives the inorder sequence. All the numbers in a line are separated by a space.
Output Specification:
For each test case, print in one line the level order traversal sequence of the corresponding binary tree. All the numbers in a line must be separated by exactly one space, and there must be no extra space at the end of the line.
Sample Input:7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
Sample Output:
4 1 6 3 5 7 2
题意:本题就给你一个后序遍历序列和中序遍历序列,让你得出该树的层次遍历序列
(这种情况我们必须要知道中序序列和其他某个序列才行)
思路:
对于这个题我们要得到它的层次遍历序列,那么我们就必须先得到这颗树,然后才能得到层次遍历序列
我们根据数据结构的相关知识,后序序列 “左右根” 中序序列“左根右” 先序序列“根左右”
所以后序遍历的最后一个元素一定是整个树的根,然后往前依次是右子树根和左子树根.,而中序遍历我们先遍历的是左子树根然后是
根然后是右子树根,所以我们现在后序遍历中确定根,然后在中序遍历中找到相应根的位置,进而就可以得到该根的左边一定是左子树
右面一定是右子树,然后递归解决问题,建立好了树,在进行层次遍历即可
实现方法:
我们定义cur这个全局遍历,cur=n,设计两个变量left和right,从后序序列的最后一个位置(树的根)开始,
每次取出一个根,cur-1在中序遍历中找到根,进而确定左右子树,假设该根的位置为root,那么根据中序遍历,它的右子树在
(root+1,right),左子树在(left,root-1)..因为后序序列是左右根,所以根节点的前面是右子树所以我们应该先递归
右子树.当left==right说明为叶子节点.将T->left right 置空后返回..
得到整个树以后再用队列进行层次遍历即可
#include<bits/stdc++.h> #define inf 0x3f3f3f3f using namespace std; typedef long long ll; int post[33],in[33]; int n,cur; typedef struct node *Tree; struct node { Tree left; Tree right; int num; }; int findroot(int x) {//在中序遍历中确定根节点位置 for(int i=1;i<=n;i++) { if(in[i]==x) { return i; } } return -1; } Tree createTree(int left,int right) {//递归建立二叉树 if(left>right) return NULL; int w=post[cur--]; int root=findroot(w); Tree T=(Tree)malloc(sizeof(node)); T->num=w; if(left==right) { T->left=NULL; T->right=NULL; } else { T->right=createTree(root+1,right); T->left=createTree(left,root-1); } return T; } void bfs(Tree T) {//层次遍历 Tree q; queue<Tree>Q; Q.push(T); int flag=0; while(!Q.empty()) { q=Q.front(); Q.pop(); if(flag!=0) printf(" "); printf("%d",q->num); if(q->left!=NULL) Q.push(q->left); if(q->right!=NULL) Q.push(q->right); flag=1; } } int main() { cin>>n; cur=n; for(int i=1;i<=n;i++) cin>>post[i]; for(int i=1;i<=n;i++) cin>>in[i]; Tree T=createTree(1,cur); bfs(T); return 0; }
拓展:
我又写了一个根据先序和中序遍历获得树并进行层次遍历的代码,方法还是一样的。
根据先序遍历的特点 “根左右”我们就先从先序遍历中确定根节点然后在中序遍历中确定根节点的位置进而找到它的左右子树
进行递归.
实现方法和上述的基本相同,不过这里的cur我们应该从头开始.然后每次+1,另外,因为先序遍历先遍历的根然后是左子
树,然后是右子树,所以我们要先递归左子树,其余的不再赘述
#include<bits/stdc++.h> using namespace std; const int maxn=1e7+10; int pre[maxn],in[maxn]; int cur,n; typedef struct Tnode *Tree; struct Tnode { Tree left; Tree right; int num; }; int findroot(int x) { for(int i=1;i<=n;i++) { if(x==in[i]) return i; } return -1; } Tree createTree(int left,int right) { if(left>right) return NULL; int r=pre[cur++]; int root=findroot(r); Tree T =(Tree)malloc(sizeof(Tnode)); T->num=r; if(left==right) { T->left=NULL; T->right=NULL; } else { T->left=createTree(left,root-1); T->right=createTree(root+1,right); } return T; } void bfs(Tree T) { Tree q; queue<Tree>Q; while(!Q.empty()) Q.pop(); Q.push(T); int flag=0; while(!Q.empty()) { q=Q.front(); Q.pop(); if(flag!=0) printf(" "); flag=1; printf("%d",q->num); if(q->left!=NULL) Q.push(q->left); if(q->right!=NULL) Q.push(q->right); } return ; } int main() { cin>>n; for(int i=1;i<=n;i++) cin>>pre[i]; for(int i=1;i<=n;i++) cin>>in[i]; cur=1; Tree S=createTree(cur,n); bfs(S); return 0; }