使用递归策略将数组转换为二叉树
Posted
技术标签:
【中文标题】使用递归策略将数组转换为二叉树【英文标题】:convert array to binary tree with recursive strategy 【发布时间】:2021-09-13 15:56:21 【问题描述】:我需要从包含一些零的向量开始创建一个二叉树,其中零表示不存在的节点。例如,如果我得到:
int a[] = 10,4,7,2,3,-1,8,9,-1,2,4,5;
我想要这样的输出:
10
/ \
4 7
/ \ \
2 3 8
/ / \ /
9 2 4 5
我的结构:
typedef struct node
int n;
struct node * dx;
struct node * sx;
*Bit_node;
搭建一个节点的方法:
Bit_node bit_new(int n)
Bit_node new_node = malloc(sizeof(struct node));
new_node -> n = n;
return new_node;
构建整棵树的方法:
Bit_node bit_arr2tree(int a[], int size, int i)
if (i>= size)
return NULL;
if(a[i] != -1)
Bit_node new_node = bit_new(a[i]);
new_node -> sx = bit_arr2tree(a, size, i*2 +1);
new_node -> dx = bit_arr2tree(a, size, i*2 +2);
return new_node;
但是在我的实现中,我的树是在不考虑“漏洞”的情况下构建的。有没有办法考虑它们,保持递归策略?
【问题讨论】:
【参考方案1】:鉴于输入数据结构不保证父子关系为i*2+1
和i*2+2
,因此并不真正需要递归解决方案。输入序列表示广度优先顺序,因此以广度优先顺序构建树会更自然。
附带说明:函数bit_new
还应该初始化sx
和dx
成员:您不想留下未定义值的那些。
以下是您编写算法的方法:
Bit_node bit_new(int n)
Bit_node new_node = malloc(sizeof(struct node));
new_node -> n = n;
new_node -> sx = NULL;
new_node -> dx = NULL;
return new_node;
Bit_node bit_arr2tree(int a[], int size)
if (size == 0)
return NULL;
// Create a temporary array to store the node pointers
Bit_node nodes[size];
// Create the nodes
for (int i = 0; i < size; i++)
nodes[i] = a[i] == -1 ? NULL : bit_new(a[i]);
// To link the nodes, use two indexes: parent and child
for (int child = 1, parent = 0; child < size; child += 2, parent++)
// Here we "skip the gaps": a parent cannot be NULL:
while (nodes[parent] == NULL)
parent++;
nodes[parent] -> sx = nodes[child];
if (child + 1 < size)
nodes[parent] -> dx = nodes[child + 1];
return nodes[0];
【讨论】:
【参考方案2】:首先,int a[] = 10,4,7,2,3,-1,8,9,-1,2,4,5;
不应该生成您期望的树,5 作为 8 的左子节点。由于 8 位于索引 6,它的左子节点将位于索引 6 * 2 + 1 == 13
。所以你的输入可能应该是int a[] = 10,4,7,2,3,-1,8,9,-1,2,4,-1,-1,5;
,在数组末尾有两个额外的-1,将5推到正确的索引。
您的实现无法工作,因为在模式中:
Bit_node new_node = malloc(...)
return new_node;
new_node
不在范围内时被访问。如果遇到 -1,您希望返回 NULL,就像您在数组越界时所做的一样。返回 NULL 表示“这里没有孩子”,这正是您想要与父框架通信的内容,以便它将丢失的孩子设置为 NULL。
修复应该非常简单:
Bit_node bit_arr2tree(int a[], int size, int i)
if (i>= size || a[i] < 0)
// ^^^^^^^^^^^
return NULL;
Bit_node new_node = bit_new(a[i]);
new_node->sx = bit_arr2tree(a, size, i * 2 + 1);
new_node->dx = bit_arr2tree(a, size, i * 2 + 2);
return new_node;
顺便说一句,我会提醒against typedeffing away pointers。这会降低代码的可读性并隐藏信息。
这是一个可运行的概念证明:
#include <stdio.h>
#include <stdlib.h>
struct Node
int data;
struct Node *left;
struct Node *right;
;
struct Node *arr2tree(int arr_len, int *arr, int i)
if (i >= arr_len || arr[i] < 0)
return NULL;
struct Node *node = malloc(sizeof(*node));
node->data = arr[i];
node->left = arr2tree(arr_len, arr, i * 2 + 1);
node->right = arr2tree(arr_len, arr, i * 2 + 2);
return node;
void print_tree(struct Node *root, int depth)
if (root)
print_tree(root->right, depth + 4);
for (int i = 0; i < depth; i++)
printf(" ");
printf("%d\n", root->data);
print_tree(root->left, depth + 4);
void free_tree(struct Node *root)
if (root)
free_tree(root->left);
free_tree(root->right);
free(root);
int main()
int a[] = 10,4,7,2,3,-1,8,9,-1,2,4,-1,-1,5;
struct Node *root = arr2tree(sizeof(a) / sizeof(a[0]), a, 0);
print_tree(root, 0);
free_tree(root);
return 0;
输出:
8
5
7
10
4
3
2
4
2
9
【讨论】:
我不明白为什么通过放置 or 条件不会停止对第一个 -1 值的递归:( 它确实在第一个 -1 值处停止递归,但仅针对递归的那个分支。每一帧都会产生两个调用——如果一个因为那个孩子不存在而提前返回 NULL(即是 -1 或超出数组的范围),另一个可能会继续递归。您可能想使用调试器并尝试使用具有 3-4 个节点的更简单的树。以上是关于使用递归策略将数组转换为二叉树的主要内容,如果未能解决你的问题,请参考以下文章
Leetcode练习(Python):树类:第108题:将有序数组转换为二叉搜索树:将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的