题目
:输入树的中序和后序排列,输出树的层次遍历。
输入样例
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
输出样例:
4 1 6 3 5 7 2
题解
:本题是二叉树遍历的一个综合考察,给定二叉树的中序与前序(或后序)遍历,求解二叉树的后序(或层次)遍历,可以归为一个大类。其解题方法都是先根据中序与前序(或后序)遍历重建二叉树,而后输出后序(或层次)遍历。因此本题步骤分为两步:
(1)重建二叉树:定义root为后序遍历中根结点的位置,left、right为中序遍历的左右边界,定义cur指针指向当前结点。定义一个变量index指向中序遍历中根节点的位置,根据根节点将树划分为左右子树,那么右子树的根结点为root-1,右子树右边界为right,右子树左边界为index+1,左子树根结点为root-right+index-1,左子树左边界为left,左子树右边界为index-1。
(2)层次遍历二叉树:对重建的二叉树进行层次遍历即可。
代码(C++)
:
#include <bits/stdc++.h>
using namespace std;
// 全局变量
vector<int> in,post,pre,level; // 定义四种遍历顺序的数组
struct TreeNode{
TreeNode* lchild;
TreeNode* rchild;
int val;
TreeNode() : val(0), lchild(nullptr), rchild(nullptr) {}
TreeNode(int x) : val(x), lchild(nullptr), rchild(nullptr) {}
};
void rebuild(int root, int left, int right, TreeNode* &cur){ //root为后序遍历中子树根结点的位置,left、right为中序遍历的左右边界
int index; // 定位root在中序遍历中的位置
if(left > right) return; // 终止条件
cur = new TreeNode(post[root]); // 定义新结点
for(index = left; index <= right; index++){
if(in[index] == post[root]){ // 在中序遍历中找到了root,index就是其位置
break;
}
}
rebuild(root - right + index -1, left, index - 1, cur->lchild);
rebuild(root - 1, index + 1, right, cur->rchild);
}
void levelOrder(TreeNode* root){
TreeNode* cur; // 指向当前结点
queue<TreeNode*> que; // 定义队列
if(root) que.push(root); // 根结点入队
while(!que.empty()){
int size = que.size();
for(int i = 0; i < size; i++){
cur = que.front();
que.pop();
level.push_back(cur->val);
if(cur->lchild) que.push(cur->lchild);
if(cur->rchild) que.push(cur->rchild);
}
}
}
int main(){
// 定义变量
TreeNode* root; //二叉树
int n,cur; //输入个数
// 输入
scanf("%d",&n);
for(int i = 0; i < n; i++){ // 输入后序遍历
scanf("%d",&cur);
post.push_back(cur);
}
for(int i = 0; i < n; i++){ // 输入中序遍历
scanf("%d",&cur);
in.push_back(cur);
}
// 主体
rebuild(n-1,0,n-1,root);
levelOrder(root);
// 输出
for(int i = 0; i < n; i++){
if(i < n-1){
cout << level[i] << " ";
}else{
cout << level[i] << endl;
}
}
return 0;
}
写在后面
这个专栏主要是我在刷题的过程中总结的一些笔记,因为我学的也很一般,如果有错误和不足之处,还望大家在评论区指出。希望能给大家的学习带来一点帮助,共同进步!!!