【问题标题】:How to set a pointer to be invalid?如何将指针设置为无效?
【发布时间】:2016-07-26 12:54:44
【问题描述】:

我编写了一个二叉搜索树并创建了一个删除节点的函数。 一般它有两个输入参数,第一个是指向需要删除的对象的指针,第二个是指向二叉搜索树根的指针。

除了节点是叶子的“最简单”的情况外,基本上我的所有情况都有效。

我的代码将应该删除的节点的内容设置为0,但是仍然有对此的引用并且它显示在树中。

*p 是应该被删除的元素。

*pBaum 指向树的根。

*p-> right 和 *p->left 是指向 *p 的左右子树的指针。

*p->conten 是 *p 的值。

叶子案例中的我的代码:

struct tnode  *deletenode(struct tnode *p, struct tnode *pBaum) 
{
    if (p !=NULL)
    {

        if ((p->left == NULL) && (p->right == NULL)) 
        {
        printf("%d Ist Blatt \n", p->content);
        free(p);
        return pBaum;
        }

基本上我“只”需要告诉指针 *p 它从现在开始无效。但是我无法找到合适的解决方案。也许你们可以帮忙。

编辑:好的,我自己尝试过将父指针设置为 NULL。

struct tnode* danglingPointerFix (struct tnode *p, int nodtodelete)
{
 if((p->right)->content = nodtodelete)
    {
        p->right = NULL;
        return 0;
    }
    if((p->left)->content = nodtodelete)
    {
        p->left = NULL;
        return 0;
    }
}

struct tnode *searchnode(struct tnode *p, int nodtodelete) 
{
if (p == NULL)
{
    printf("Baum ist leer oder Element nicht vorhanden \n");
    return 0;
}
if ( p -> content == nodtodelete)
{
    return p;
}
if (p->content < nodtodelete)
{
    danglingPointerFix(p, nodtodelete);
    return searchnode (p->right, nodtodelete);
}
if (p->content > nodtodelete)
{
    danglingPointerFix(p, nodtodelete);
    return searchnode(p->left, nodtodelete);
}
}

但是我有段错误,也许在某个地方可以看到,因为在我看来这个解决方案应该可以工作。

【问题讨论】:

  • 是否有理由将指针设置为 NULL 不是一个可行的选项?但也许你看错了。通常在维护这样的树时,您会设置左右节点的指针,以便它们不再引用已删除的节点。
  • 你没有忘记对p的引用吗?
  • 0XDEADBEEF 有时用于将指针标记为无效
  • @BobJarvis 我试过了,但没用。问题是 *p 是一个指向节点的指针,但它并没有告诉 p-> right 或 p->left 来自前一个节点的指针它是无效的。
  • @Cornstalks:我正在编辑我的评论,试图轻轻地引导 OP 朝那个方向发展。

标签: c pointers binary-search-tree nodes


【解决方案1】:

虽然你已经释放了叶子节点,但父节点仍然保留着悬空指针。

解决方法之一是添加以下函数:

struct tnode  *deleteLeftNode(struct tnode *parent, struct tnode *pBaum) {

    if (parent) {
        deletenode(parent->left, pBaum);
        parent->left = NULL;
    }
    return pBaum;
}

struct tnode  *deleteRightNode(struct tnode *parent, struct tnode *pBaum) {

    if (parent) {
        deletenode(parent->right, pBaum);
        parent->right = NULL;
    }
    return pBaum;
}

【讨论】:

  • 我自己尝试过一些非常相似的东西,也许你可以看到分段错误。
  • 如果右节点 NULL 并且您尝试删除左节点它将崩溃。您需要== 进行比较。 (单个= 是赋值)。试试if(p-&gt;right &amp;&amp; (p-&gt;right)-&gt;content == nodtodelete)
【解决方案2】:

您必须找到指向要删除的叶子的父节点。找到后,应将父级中相应的leftright 指针设置为NULL

所以你的删除应该是这样的:

struct tnode  *deletenode(struct tnode *p, struct tnode *pBaum) 
{
    if (p !=NULL)
    {

        if ((p->left == NULL) && (p->right == NULL)) 
        {
            // This is a leaf --> It may be deleted
            deleteNodeInParent(pBaum, p);

            printf("%d Ist Blatt \n", p->content);
            free(p);
            return pBaum;
        }

然后你需要实现deleteNodeInParent。它将与您当前的搜索功能非常相似,只是您将检查是 left == p 还是 right == p 并且 - 如果是 - 将值设置为 NULL 并返回。

类似:

void deleteNodeInParent(struct tnode *p, struct tnode *pDeleted) 
{
    if (p == NULL)
    {
      printf("Baum ist leer oder Element nicht vorhanden \n");
      return;
    }
    if (p->left == pDeleted)
    {
        p->left = NULL;
        return;
    }
    if (p->rigth == pDeleted)
    {
        p->rigth = NULL;
        return;
    }

    if ( p -> content == pDeleted->content )
    {
      // Can only happen for head - just return
      return;
    }
    if (p->content < pDeleted->content )
    {
      deleteNodeInParent(p->right, pDeleted);
      return;
    }
    if (p->content > pDeleted->content )
    {
      deleteNodeInParent(p->left, pDeleted);
      return;
    }
}

也就是说,我认为如果您使用指向父级的指针扩展 struct tnode 会容易得多。

【讨论】:

  • 我自己尝试了一些非常相似的方法,也许您可​​以在我的 danglingPointerFix 方法中看到分段错误。
  • @RobinSchmidt - 好吧,您在 danglingPointerFix 函数中执行分配 = 而不是测试 ==。我不确定这是否会导致分段错误。但先解决这个问题。
  • @RobinSchmidt - 在执行if ((p-&gt;right)-&gt;content ... 之前,您还必须检查p-&gt;right == NULL,因为您所知道的是p不是NULL,但p-&gt;leftp-&gt;rightmaybe @ 987654339@
  • @RobinSchmidt - 您的方法似乎有点奇怪,因为除了删除节点之外,可能从不调用搜索功能。这不是我对 searchnode 函数的期望。
猜你喜欢
  • 1970-01-01
  • 2020-08-04
  • 2017-11-09
  • 1970-01-01
  • 2018-05-06
  • 2017-10-06
  • 2017-09-05
  • 1970-01-01
  • 2015-05-09
相关资源
最近更新 更多