版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Xiblade/article/details/82994378
树的遍历常考,此题考根据后续遍历和中序遍历求二叉树,之后输出其层次遍历。
这种题以选择题出题较简单,但机试题求解可能会有一些边界条件。
#include<cstdio>
#include<queue>
using namespace std;
struct Node{
int data;
//int level; // 因为题目要求层次遍历,所以添加这个东西
Node *lchild;
Node *rchild;
Node(){
data = -1;
//level = 0;
lchild = NULL;
rchild = NULL;
}
};
const int MAXN = 100;// 以数组存放临时数据
int post[MAXN] = {0};
int in[MAXN] = {0};
// 此函数的L 和 R都是左闭右闭的
Node *create(int postL, int postR, int inL, int inR){
// 递归边界 :除去中序序列以外的序列为空
if(postL > postR){
return 0;
}
// 构造根节点
Node *root = new Node;
root -> data = post[postR];
// 在中序序列中查找根节点
int rootNum = -1;
for(int i = inL; i <= inR; i++){
if(in[i] == root -> data){
rootNum = i;
break;
}
}
// 这种边界应该不会出现 写下来以防万一
if(rootNum == -1){
delete(root);
return NULL;
}
int numL = rootNum - inL;
// 那么 现在中序序列中
// 左子树: [inL, rootNum - 1] 一共 rootNum - inL
// 即 numL个
// 右子树: [rootNum + 1, inR] 一共 inR - rootNum 个
// 后序序列中
// 以下两行把后续遍历的左右装反了
// 左子树: [postR - 1 - numL, postR - 1]
// 右子树: [postL, postR - 2 - numL]
// 左子树: [postL, postL + numL - 1]
// 右子树: [postL + num , postR - 1] // 注意 这里也要扣1
root -> lchild = create(postL, postL + numL - 1, inL, rootNum - 1);
root -> rchild = create(postL + numL, postR - 1, rootNum + 1, inR);
return root;
}
void levelOrder(Node *root){
if(root == NULL){ // 空树 不遍历
return;
}
queue<Node*> q; // 根节点是存地址
q.push(root);
while(!q.empty()){
Node *now = q.front();
printf("%d", now -> data);
q.pop();
if(now -> lchild != NULL)
q.push(now -> lchild);
if(now -> rchild != NULL)
q.push(now -> rchild);
if(!q.empty()) printf(" ");
}
}
int main(){
int n = -1;
scanf("%d", &n);
if(n == 0){ // 树是空树的情况
printf("\n");
return 0;
}
// 树不是空树的情况
// 将后序和中序遍历结果扫描进数组
for(int i = 0; i < n; i++){
scanf("%d", &(post[i]));
}
for(int i = 0; i < n; i++){
scanf("%d", &(in[i]));
}
// 开始递归地由后续遍历序列到中序遍历序列
// 构造二叉树
Node *root = create(0, n - 1 , 0, n - 1); // 注意 左闭右闭
// 构造完成 开始层次遍历二叉树
levelOrder(root);
return 0;
}