Build A Binary Search Tree
题目阐述
A Binary Search Tree (BST) is recursively defined as a binary tree which has the following properties:
The left subtree of a node contains only nodes with keys less than the node’s key.
The right subtree of a node contains only nodes with keys greater than or equal to the node’s key.
Both the left and right subtrees must also be binary search trees.
Given the structure of a binary tree and a sequence of distinct integer keys, there is only one way to fill these keys into the tree so that the resulting tree satisfies the definition of a BST. You are supposed to output the level order traversal sequence of that tree. The sample is illustrated by Figure 1 and 2.
Input Specification:Each input file contains one test case. For each case, the first line gives a positive integer N (<=100) which is the total number of nodes in the tree. The next N lines each contains the left and the right children of a node in the format “left_index right_index”, provided that the nodes are numbered from 0 to N-1, and 0 is always the root. If one child is missing, then -1 will represent the NULL child pointer. Finally N distinct integer keys are given in the last line.
Output Specification:
For each test case, print in one line the level order traversal sequence of that tree. All the numbers must be separated by a space, with no extra space at the end of the line.
Sample Input:
9
1 6
2 3
-1 -1
-1 4
5 -1
-1 -1
7 -1
-1 8
-1 -1
73 45 11 58 82 25 67 38 42
Sample Output:
58 25 82 11 38 67 45 73 42
代码实现
#include <stdio.h>
#include <algorithm>
#include <queue>
using namespace std;
struct node {
int val, left, right;
}NODE[105];
int n, l[105], r[105], value[105], b[105], cnt;
void dfs(int f) {
NODE[f].left = l[f];
NODE[f].right = r[f];
if (NODE[f].left != -1) dfs(NODE[f].left);
if (NODE[f].right != -1) dfs(NODE[f].right);
}
void help(int head) {
if (head == -1) return;
help(NODE[head].left);
NODE[head].val = cnt ++;
help(NODE[head].right);
}
int main() {
scanf("%d", &n);
for (int i=0; i<n; i++) {
scanf("%d%d", &l[i], &r[i]);
if (l[i] != -1) b[l[i]] = 1;
if (r[i] != -1) b[r[i]] = 1;
}
for (int i=0; i<n; i++) {
scanf("%d", &value[i]);
}
sort(value, value+n);
int head;
for (head=0; head<n; head++)
if (b[head] == 0) break;
dfs(head);
cnt = 0;
help(head);
queue<int> q;
q.push(head);
int flag = true;
while (!q.empty()) {
int p = q.front();
q.pop();
if (flag) {
printf("%d", value[NODE[p].val]);
flag = false;
} else printf(" %d", value[NODE[p].val]);
if (NODE[p].left != -1) q.push(NODE[p].left);
if (NODE[p].right != -1) q.push(NODE[p].right);
}
return 0;
}
总结
- PAT里树的经典题型,这里还是通过树节点的下标之间的关系来构建一棵树,-1为空,以及BST的性质的运用,层次遍历的考察;
- 整体思路是找到头节点,然后进行一遍深搜,将所有节点之间的父子关系确定下来,然后再中序遍历,将所有排序好的数值对应的value数组下标赋值到NODE每个节点的val里去,最后再层次遍历即可;
- 本来以为这50行代码已经足够简便,但看了柳神的博客,她直接在输入的时候就将左右节点下标确定好了,相比之下啊,我使用l[105]和r[105]数组显得多此一举了,然后一遍中序遍历将排序后的value[]数组里的数值直接写入node节点里的val里去,genius!简直找不到还有比这更快更美的思路了。
- 不过其实一开始看到层次遍历,想起柳神之前通过固定分配数组位置来输出所有节点的思路,不通过队列,简直6到飞起;当然那时的节点也限制在30个左右,在一个int长度里可以搞定的数组,但这里是100个,2^100显然不太可行了。