4279.笛卡尔树
思路
主要分为两个步骤:
建树
因为题目说到这棵树满足堆的性质,并且是一个小根堆,所以所有子树的根节点都是最小值。并且题目给出输入的序列是一个中序遍历。
所以我们只需要在这一个序列当中进行二分递归,找到区间当中最小值,然后以这个最小值的位置开始二分,递归构建出整棵树。
遍历
直接用 bfs 即可。注意判断左节点或者右节点不空(此处用 -1 表示)的时候才可以加入到队列。
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 40;
struct Node {
int l, r, w;
} tree[N];
queue<int> q;
int getmin(int l, int r) {
int res = l;
for (int i = l; i <= r; i++)
if (tree[res].w > tree[i].w)
res = i;
return res;
}
int dfs(int l, int r) {
if (l > r)
return -1;
// 找到每个子树的根节点,根节点都是那个区间里面最小的数
// 因为输入序列是树的中序遍历,所以可以这样干,而且满足小根堆的性质
int root = getmin(l, r);
tree[root].l = dfs(l, root - 1); // 找树的左子树
tree[root].r = dfs(root + 1, r); // 找树的右子树
return root; // 返回每一个子树的根节点
}
void bfs(int root) {
q.push(root); // 从根开始一层层遍历
while (!q.empty()) {
int t = q.front(); // 取到根节点 t
q.pop(); // 弹 出
cout << tree[t].w << " "; // 输 出
if (tree[t].l != -1)
q.push(tree[t].l); // 看这个节点 t 的左边还有没有节点,遍历下一层
if (tree[t].r != -1)
q.push(tree[t].r); // 看这个节点 t 的右边还有没有节点,遍历下一层
}
}
int main() {
int n;
cin >> n;
for (int i = 0; i < n; i++)
cin >> tree[i].w;
// 建树
int root = dfs(0, n - 1);
// bfs 层序遍历
bfs(root);
return 0;
}