思路
对于完全二叉树,除去最后一层可能不满,剩下的层组成的是满二叉树。
所以可以先得到当前根的深度,
n
l
a
s
t
=
n
−
(
2
h
−
1
)
n_{last}=n - (2^h - 1)
nlast=n−(2h−1),
n
n
n为当前区间的节点数。
那么除掉最后一层的节点数,根的左、右节点数是相同的。故
n
h
a
l
f
=
n
−
n
l
a
s
t
2
n_{half} =\frac{n - n_{last}}{2}
nhalf=2n−nlast
再根据二叉搜索树的性质可以确定根。
值得注意的是,确定根的时候,得考虑到最后一层的节点由<root->val
和>root->val
的两部分组成。
代码
#include<bits/stdc++.h>
using namespace std;
vector<int> a;
struct TreeNode {
int val;
TreeNode * left, * right;
TreeNode()=default;
TreeNode(int v) : val(v), left(nullptr), right(nullptr){};
};
TreeNode * build_tree(int l, int r) {
if(l > r)
return nullptr;
int len = r - l + 1; // [l, r]
int s = 1, inner = 1;
while((1 << (s + 1)) - 1 < len) {
++s;
inner = (1 << s) - 1;
}
int half = inner / 2;
int n_last = len - inner, n_right_last = 0; // 区分最后一层,大于root和小于的节点
if(n_last > (1 << s) / 2)
n_right_last = n_last - (1 << s) / 2;
int idx = r - half - n_right_last;
auto root = new TreeNode(a[idx]);
root->left = build_tree(l, idx - 1);
root->right = build_tree(idx + 1, r);
return root;
}
void levelorder(TreeNode * root) {
queue<TreeNode*> q;
q.push(root);
printf("%d", root->val);
while(! q.empty()) {
auto node = q.front();
q.pop();
if(node != root)
printf(" %d", node->val);
if(node->left)
q.push(node->left);
if(node->right)
q.push(node->right);
}
printf("\n");
}
int main() {
int n;
cin >> n;
a.resize(n);
for(int i = 0; i < n; ++i)
cin >> a[i];
sort(a.begin(), a.end());
auto root = build_tree(0, n - 1);
levelorder(root);
}