L2-035完全な二分木のシーケンストラバーサル(25ポイント)
二分木。各層のノード数が最大に達すると、二分木は完全な二分木になります。深さがDノードとNノードのバイナリツリーの場合、そのノードが同じ深さの完全なバイナリツリーのシーケンストラバーサルの最初のNノードに対応する場合、そのようなツリーは完全なバイナリツリーです。
完全な二分木のポストオーダートラバーサルを前提として、ツリーのトラバーサルの結果を示してください。
入力フォーマット:
ツリー内のノード数である正の整数N(≤30)を最初の行に入力します。2行目は、100を超えないN個の正の整数であるポストオーダートラバーサルシーケンスを示しています。同じ行のすべての数字はスペースで区切られます。
出力フォーマット:
ツリーの走査シーケンスを1行で出力します。すべての数字は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;
}