【问题标题】:Binary Tree Deletion二叉树删除
【发布时间】:2015-01-14 07:40:00
【问题描述】:

假设:deleteTree() 函数删除树,但不会将 root 更改为 NULL,如果 deleteTree() 的用户没有将 root 更改为 NULL 并尝试使用 root 指针访问值,这可能会导致问题。我们可以修改 deleteTree() 函数以引用根节点,这样就不会出现这个问题。

[链接]http://www.geeksforgeeks.org/write-a-c-program-to-delete-a-tree/

疑问:在 deleteTree 函数中,从主节点传递了节点的副本,那么如何在 deleteTree() 中释放所有这些节点的实际内存。据说树被删除了,但是要删除的树不应该传递地址。另外,如果我们认为树实际上被删除了,那么根节点也会随之被删除,那么为什么它在主节点中不更改为 NULL?

void deleteTree(struct node* node) 
{
  if (node == NULL) return;
  deleteTree(node->left);
  deleteTree(node->right);
  printf("\n Deleting node: %d", node->data);
  free(node);
}
int main()
{
  struct node *root = newNode(1); 
  root->left            = newNode(2);
  root->right          = newNode(3);
  root->left->left     = newNode(4);
  root->left->right   = newNode(5); 

  deleteTree(root);  
  root = NULL;

  printf("\n Tree deleted ");

  getchar();
  return 0;
}

修改后的代码:

void _deleteTree(struct node* node)
{
  if (node == NULL) return;

  _deleteTree(node->left);
  _deleteTree(node->right);
  printf("\n Deleting node: %d", node->data);
  free(node);
}


void deleteTree(struct node** node_ref)
{
  _deleteTree(*node_ref);
  *node_ref = NULL;
}

int main()
{
  struct node *root = newNode(1);
  root->left            = newNode(2);
  root->right          = newNode(3);
  root->left->left     = newNode(4);
  root->left->right   = newNode(5);


  deleteTree(&root);
  printf("\n Tree deleted ");

  getchar();
  return 0;
}

在这种情况下,如果我们在 main 而不是在 deleteTree 函数中设置 root=NULL 怎么办?

【问题讨论】:

  • @Sourav Ghosh 在第一个代码中,只传递了节点指针,而不是它的地址,如果我们希望将更改反映在 deleteTree 函数之外,我们应该传递我的地址知道。
  • 对不起,我误读了您的代码。删除了 cmets。
  • @Sourav Ghosh 但是为什么我们不能在第一种情况下将 root 设置为 NULL 而在第二种情况下可以这样做呢?

标签: c tree


【解决方案1】:

您混淆了两个概念 - 内存释放和将指针设置为 NULL。通过使用free,内存被释放,指针现在指向一块未分配的内存。通过将 node* 设置为 NULL,您表明该指针无效 - 您可以看到代码对此进行了检查 - if (node ==NULL) return;。如果您只是将根设置为 NULL,则会造成内存泄漏,因为指向的内存仍处于分配状态。

另外 - It is said the tree is deleted but for the tree to be deleted shouldn't we pass the address - 您正在传递地址 - deleteTree(&root); - root 是一个包含根节点地址的节点*。

希望这会有所帮助。

【讨论】:

  • 是的,我们在第二种情况下传递了地址,但是在第一种情况下,我们没有在那里传递地址,我们传递的是根。
  • 在第一种情况下,您传递 root 这是一个 node* 类型 - 一个地址。
  • node* 基本上说 root 是一个结构节点类型指针,它是一个地址吗?我们不是只传递第一种情况下的指针吗?
  • 指针是一个包含地址的变量 - cplusplus.com/doc/tutorial/pointers
  • 是的,所以通过传递指针,我们实际上可以删除节点,但为什么我们不能将根节点设置为空呢?在删除函数中,我们删除了包括根节点在内的所有节点,然后我们将根节点设置为 null,这样就不会发生内存泄漏,但这里说的是 main 中的 root=null 实际上不会发生?跨度>
【解决方案2】:

在第一个代码中,函数void deleteTree(struct node* node)调用自身(递归)来释放每个节点的内存。It is said the tree is deleted but for the tree to be deleted shouldn't we pass the address,实际上para node是一个节点的地址,它是一个指针(@987654324 @)。当你调用free(node) 时,你释放了node 指向的内存,而不是节点本身。

至于将root设置为NULL,第二个代码在逻辑上与您的第一个代码相同。如果函数void deleteTree(struct node** node_ref)是内联的,那么编译后就和你的第一个代码一样。

【讨论】:

  • 我要问的是第一种情况,为什么我们不能在主中将根设置为 null,树被删除了,但是在删除它之后,我们将根设置为 null没有指向任何未分配的内存位置,但是这里说根没有变化太空,为什么会这样?
猜你喜欢
  • 2011-03-08
  • 2017-07-28
  • 2018-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多