L2-035 完全二叉树的层序遍历 (25分)
一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是完美二叉树。对于深度为 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
解题
还是二叉树的遍历,这里要求输出层序遍历则需要用到bfs,而题目给出的是后序遍历(dfs)因此需要建树求出层序遍历,建树的关键是找出左右子树的节点个数,本题需利用完全二叉树的性质。
现在要找出完全二叉树中左子树的个数,假设完全二叉树T共有N个节点,即
- N左 + N右 = N - 1
开始左子树节点个数为0,然后
+ 1, + 2,+4,+8,+16,…,+,…
发现该规律,利用起来,一直加,直到所有子树节点加完,统计出左子树节点个数,再利用dfs遍历建树,最后bfs遍历树得到层序遍历。
代码
#include <algorithm> //L2-035 完全二叉树的层序遍历 (25分)
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
vector<int> back, num;
typedef struct TNode {
TNode *left, *right;
int value;
} * Tree;
Tree dfs(int l, int r, Tree T) { //建树
if (l > r) return NULL;
if (!T) T = new TNode();
T->value = back[r];
int A = 0; //记录左子树长度
int len = 1; //单行的大小
bool isLeft = true;
int cnt = 0;
for (int i = l; i < r; i++) {
cnt++;
if (isLeft) A++;
if (cnt == len) { //记录完其中一条子树的一行时
cnt = 0;
if (!isLeft) len <<= 1; //如果记录一行最后一个
isLeft = !isLeft;
}
}
T->left = dfs(l, l + A - 1, T->left);
T->right = dfs(l + A, r - 1, T->right);
return T;
}
void bfs(Tree T) {
queue<Tree> q;
q.push(T);
while (!q.empty()) {
Tree T = q.front();
num.push_back(T->value);
q.pop();
if (T->left) q.push(T->left);
if (T->right) q.push(T->right);
}
}
int main() {
int N;
cin >> N;
back.resize(N);
for (int i = 0; i < N; i++) cin >> back[i];
Tree T = dfs(0, back.size() - 1, NULL);
bfs(T);
for (int i = 0; i < num.size(); i++) {
if (i) cout << " ";
cout << num[i];
}
cout << endl;
system("pause");
return 0;
}