像往常一样,杜克林在这里触及了重点。这个想法是使用foo 作为链表中的“下一个”指针。因此,树中的每一层都被视为节点的链表。
我的代码逐级遍历树,它为下一级的foo 指针设置了正确的值,从而正确形成了一个链表。同时,它会打印当前级别的值。
注意:我假设兄弟姐妹是指该级别中的下一个节点。如果您指的是具有相同父节点的另一个节点,那么它会有点棘手,并且需要进行深入的更改。
void print_bfs_aux(struct Node *);
void print_bfs(struct Node *root) {
root->foo = NULL;
print_bfs_aux(root);
}
void print_bfs_aux(struct Node *root) {
if (!root)
return;
struct Node *next_level = NULL;
struct Node *prev = NULL;
for (struct Node *current = root; current != NULL; current = current->foo) {
printf("\t%d", current->data);
struct Node *new_prev = NULL;
if (current->left) {
new_prev = current->left;
} else if (current->right) {
new_prev = current->right;
} else {
new_prev = prev;
}
if (prev && new_prev != prev)
prev->foo = new_prev;
if (current->left && current->right) {
/* assert: new_prev = current->left */
current->left->foo = current->right;
new_prev = current->right;
}
prev = new_prev;
if (!next_level) {
if (current->left)
next_level = current->left;
else if (current->right)
next_level = current->right;
}
}
if (prev)
prev->foo = NULL;
printf("\n");
print_bfs_aux(next_level);
}
在每次迭代中,prev 指向的节点是当前正在为下一级构建的链表中的最后一个节点,current 是我们正在从当前级别访问(和打印)的节点。 next_level 是下一级列表的头部。这个想法不是很复杂,但是代码很微妙,因为它需要优雅地处理任意不平衡的树。
客户端代码应该调用print_bfs(),这是初始化根的foo 的入口点。代码不假定foo 被初始化为NULL。它也(希望)适用于任何类型的不平衡树,以及完美平衡的树。只是在为下一级构造链表的时候注意不要搞砸了。
顺便说一下,如果你想快速测试一下,这是我用过的:
int main(void) {
struct Node nodes[100];
int node, left, right;
while (scanf("%d %d %d", &node, &left, &right) == 3) {
if (left == -1)
nodes[node].left = NULL;
else
nodes[node].left = &nodes[left];
if (right == -1)
nodes[node].right = NULL;
else
nodes[node].right = &nodes[right];
nodes[node].data = node;
}
print_bfs(&nodes[0]);
return 0;
}
不过有一点建议:如果您的面试官进一步要求您开发一些测试例程,请不要编写这样的代码;这只是执行一些基本测试的一种快速肮脏的方式。
您可能想尝试的一些输入测试:
/* Input for test 1 */
0 1 2
1 -1 4
2 5 6
4 10 11
5 12 13
6 14 15
10 -1 -1
11 -1 -1
12 -1 -1
13 -1 -1
14 -1 -1
15 -1 -1
/* A fully balanced tree */
0 1 2
1 3 4
2 5 6
3 8 9
4 10 11
5 12 13
6 14 15
8 -1 -1
9 -1 -1
10 -1 -1
11 -1 -1
12 -1 -1
13 -1 -1
14 -1 -1
15 -1 -1
/* An unbalanced tree */
0 1 2
1 -1 -1
2 5 -1
5 12 13
12 -1 -1
13 -1 -1
/* Something a little bit longer */
0 1 2
1 3 -1
2 5 6
3 8 9
5 12 13
6 14 15
8 -1 -1
9 -1 -1
12 -1 -1
13 -1 -1
14 -1 -1
15 16 -1
16 17 -1
17 18 -1
18 -1 19
19 -1 20
20 -1 -1