一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是完美二叉树。对于深度为 D 的,有 N 个结点的二叉树,若其结点对应于相同深度完美二叉树的层序遍历的前 N 个结点,这样的树就是完全二叉树。
给定一棵完全二叉树的后序遍历,请你给出这棵树的层序遍历结果。
输入格式:
输入在第一行中给出正整数 N(≤30),即树中结点个数。第二行给出后序遍历序列,为 N 个不超过 100 的正整数。同一行中所有数字都以空格分隔。
输出格式:
在一行中输出该树的层序遍历序列。所有数字都以 1 个空格分隔,行首尾不得有多余空格。
输入样例:
8
91 71 2 34 10 15 55 18
输出样例:
18 34 55 71 2 10 15 91
我的思路:
关键名词:完全二叉树、后序遍历、层序遍历
1)二叉树的一个编号特点是:若根节点的编号是1的话,左儿子结点的编号是2i(其父亲结点设为i),右儿子结点的编号是2i+1;
2)给了我们后续遍历,我们可以构建一个DFS函数,我感觉里面最少见的是在DFS里面cin读取,首先说一下这个好处,这样可以直接建立编号与数据的联系。那么为什么我们可以用DFS来读取呢?因为我们得知这是一个完全二叉树,而不是其他普通的二叉树,我们得知后序遍历(或是 前序遍历或是中序遍历中的一个)就可以构建出一整个完全二叉树;
献上AC代码:
#include <iostream>
using namespace std;
const int N = 35;
int n;
struct tree{
int l, r, dat;
#define l(x) tr[x].l
#define r(x) tr[x].r
#define v(x) tr[x].dat
}tr[N];
void build(){
for(int i = 1; i <= n; i ++){
if(2*i <= n) l(i) = 2*i;
if(2*i+1 <= n) r(i) = 2*i+1;
}
}
void dfs(int t){
if(t > n) return;
if(l(t)) dfs(l(t));
if(r(t)) dfs(r(t));
cin >> v(t);
}
int main(){
cin >> n;
build();
dfs(1);
for(int i = 1; i <= n; i ++){
if(i > 1) printf(" ");
printf("%d", v(i));
}
return 0;
}
思考:
这两个题都是关于二叉树的题,而它们在这个构建二叉树上有明显的不同。我思考后觉得,这两个不同应该是以下原因:
1)这个题我们已知是完全二叉树,而且只知道后序遍历,所以我们顺着后序遍历的遍历方法去读取数据会比较方便;
2)另一个题我们只知道是二叉树,什么类型的二叉树我们不知道。我们知道了后序遍历和中序遍历,所以从上往下遍历会更加方便;
即:
1.已知:完全二叉树 + 一种遍历(后 / 前 / 中)→ 结构固定,从下往上填值更方便
2.已知:中序 + 后序 / 中序 + 前序,但不知道树形状→ 结构不固定,必须从上往下递归划分区间
1333



被折叠的 条评论
为什么被折叠?



