我试图了解二叉树中节点的删除。这是我从教程中找到的代码片段,它解释了相同的内容。
节点如下所示:
struct node
{
int key_value;
struct node *left;
struct node *right;
};
来源:http://www.cprogramming.com/tutorial/c/lesson18.html
void destroy_tree(struct node *leaf)
{
if( leaf != 0 )
{
destroy_tree(leaf->left);
destroy_tree(leaf->right);
free( leaf );
}
}
我怀疑free(leaf)
部分。我的意思是,作者声称这将以递归方式从最左下角开始删除所有节点。但是不是free(leaf)
只是释放叶子指针的内存吗? Aren所有节点仍然连接?清算是如何进行的?
答案 0 :(得分:3)
我以图形方式向您展示树的变化:
START:
10
/ \
6 14
/ \ / \
free 8 11 18
10
/ \
6 14
/ \ / \
free free 11 18
10
/ \
free 14
/ \ / \
free free 11 18
10
/ \
free 14
/ \ / \
free free free 18
10
/ \
free 14
/ \ / \
free free free free
10
/ \
free free
/ \ / \
free free free free
free
/ \
free free
/ \ / \
free free free free
当然最终,节点没有连接,它们不再存在。我刚刚在图片中展示了它们在此算法过程中会如何变化。如果您有任何其他问题,请随时提出。
我强烈建议您,只要您无法理解树递归的工作方式,就可以在纸上写一张图片,然后像我上面写的那样通过算法。
答案 1 :(得分:2)
在您发布的链接中,作者有一个如下所示的树:
10 / \ 6 14 / \ / \ 5 8 11 18
递归删除功能的工作方式是向左下方,然后是右侧,然后删除节点。因此,在上面将发生以下情况(从包含10的节点开始)
Node 10 -> leaf!=null -> destroy_leaf(leaf->left)
Node 6 -> leaf!=null -> destroy_leaf(leaf->left)
Node 5 -> leaf!=null -> destroy_leaf(leaf->left)
null -> do nothing and return back to Node 5
Node 5 - destroy_leaf(leaf->right)
null -> do nothing and return back to Node 5
free(Node 5) and return back to Node 6
Node 6 -> destroy->leaf(leaf->right)
Node 8 -> leaf!=null -> destroy_leaf(leaf->left)
null -> do nothing and return back to Node 8
Node 8 -> destroy_leaf(leaf->right)
null -> do nothing and return back to Node 8
free(node 8) and return back to Node 6
free(node 6) and return back to Node 10
Node 10 -> destroy_left(leaf->right)
上面显示了该函数将如何从节点10向左递归。由于节点是free
d,它们的父节点将指向已释放的内存,但这很好,因为你最终将丢弃递归展开时释放父节点并释放父节点。
答案 2 :(得分:2)
答案 3 :(得分:1)
你是对的。它正在从C" Allocated Memory"中回收内存,这很可能是堆。由于您要删除整个树,因此它不能正确地重建节点,因为它们会在树上进行重新计算,因为它们也将被销毁。
此代码不会删除或更确切地说"删除"树中的一个元素,它会在给定叶节点的情况下销毁整个树。
来自网站
下面显示的destroy_tree实际上将释放存储在节点leaf:tree下的树中的所有节点。
答案 4 :(得分:1)
但是没有(叶子)只返回叶子指针的内存吗?
是。但那不是全部。看看对free
的调用,你看到被叫什么?
Aren所有节点仍然连接?
没关系因为......
如何进行清算?
destroy_tree
的递归调用向左和向下递减,这将反过来执行递归破坏,最后它释放,返回调用者,释放等等。最后,整棵树都被释放了。
答案 5 :(得分:1)
free(leaf)
调用释放为指针leaf
指向的变量分配的内存。这里,它释放了struct node
类型的变量占用的所有12个字节 - 即int value
的4个字节,node *left
指针的4个字节和4个字节的node *right
指针。
通过调用destroy_tree(left)
,您将删除left
指向的子树。你可以把它想象成放火到树的顶部并观察它从树叶烧掉,首先是左边的树枝,然后是右边的树枝。
答案 6 :(得分:1)
让我们尝试从这段代码中理解它:
void delete(struct node* node)
{
if(node==NULL)
return;
delete(node->left);
delete(node->right);
free(node)
}
在此代码控件中将首先转到最左边的叶子,它将从那里开始删除(如同删除父级之前我们必须删除其子级) 以树为例:
1
/ \
2 3
/ \
4 5
所以首先释放节点4的内存,然后释放节点5,因为free不返回任何值(内存引用被删除)所以父节点也将指向NULL,所以在5 2之后将被删除。 我希望这有帮助。