【问题标题】:Printing a pointer after its deletion prints null between parentheses在删除指针后打印指针在括号之间打印空
【发布时间】:2020-01-15 13:00:04
【问题描述】:

我写了一段代码,递归地在树中找到最小的字符串并将其删除。但是,删除节点后打印树返回 (null)。

static char* findMinimum(TreeNodePtr treePtr){
  if(treePtr->left == NULL){
    printf("Minimum node is %s\n", treePtr->item);
    char * temp = treePtr->item;
    (treePtr)->item = NULL;
    return(temp);
  }
  else{
    findMinimum(treePtr->left);
  }
}

我认为这个函数可以工作,因为即使使用不同的字符串,它也会删除最小值。我应该写一个条件来确保 NULL 指针不会被打印吗?以防万一,这里还有打印功能:

static void printTree(TreeNodePtr treePtr) {
  if (treePtr != NULL) {
    level++;
    printTree(treePtr->left);
    printf(">%*s%s\n", level*5, "", treePtr->item);
    printTree(treePtr->right);
    level--;
  }
}

【问题讨论】:

  • 假设其中一个父节点没有左子节点,您的代码(应该)删除父节点,那么如果存在右子节点怎么办?你怎么处理? PLUS 我猜item 必须是一个字符串,那么将它分配给NULL 会做什么?

标签: c pointers recursion binary-search-tree


【解决方案1】:

您正在删除最小节点而不更改其父节点的子节点。如果您删除一个节点,您还应该将其父节点更改为指向 NULL。请注意,将 treePtr->item 设置为 NULL 并不能实现这一点,因为 treePtr->left 指向 TreeNodePtr,而不是其 item 成员。

【讨论】:

    【解决方案2】:

    这个函数

    static char* findMinimum(TreeNodePtr treePtr){
      if(treePtr->left == NULL){
        printf("Minimum node is %s\n", treePtr->item);
        char * temp = treePtr->item;
        (treePtr)->item = NULL;
        free(treePtr->item);
        return(temp);
      }
      else{
        findMinimum(treePtr->left);
      }
    }
    

    没有意义。

    对于初学者这部分或代码

      else{
        findMinimum(treePtr->left);
      }
    

    什么都不返回。所以这个函数已经有未定义的行为。

    同时考虑这些陈述

        (treePtr)->item = NULL;
        free(treePtr->item);
    

    free 的调用什么也没做。

    否则,当函数返回指向已删除字符串的指针时,您将交换语句。同样,该程序将具有未定义的行为。

    此外,当最小的字符串已被删除时,该函数在第二次被调用时的行为也不清楚。

    而且您必须动态创建将从函数返回的最小字符串的副本。

    我会建议以下功能实现(未经测试)。

    static char * findMinimum( TreeNodePtr treePtr )
    {
        if ( treePtr == NULL || treePtr->item == NULL ) return NULL;
    
        if ( treePtr->left == NULL || treePtr->left->item == NULL )
        {
            char *s = malloc( strlen( treePtr->item ) + 1 );
            strcpy( s, treePtr->item );
    
            free( treePtr->item );
            treePtr->item = NULL;
    
            return s;
        }
        else
        {
            return findMinimum( treePtr->left );
        }
    }
    

    【讨论】:

    • 这样调用函数不是实现递归的必要条件吗?到目前为止,我不知道有其他方法可以做到这一点。关于第二部分,会解决这个问题。编辑:刚刚意识到你的意思,哎呀
    • @Impasse 正如我所写,该函数具有未定义的行为。如果第一个节点不包含最小字符串,则将控件传递给下一个左侧节点并且函数不返回任何内容。
    【解决方案3】:

    我在您的 findMinimum 函数中发现了几个问题:

    1) 在 findMinimum 的 else-case 中返回什么?我猜你忘了加return

    static char* findMinimum(TreeNodePtr treePtr){
      if(treePtr->left == NULL){
        printf("Minimum node is %s\n", treePtr->item);
        char * temp = treePtr->item;
        (treePtr)->item = NULL;
        free(treePtr->item);
        return(temp);
      }
      else{
        return findMinimum(treePtr->left);  // added return
      }
    }
    

    2) 你的树是二叉搜索树吗?考虑在这种情况下会发生什么:

       root-node
       /       \ 
    smallest   largest
        \
       not-smallest
    

    您应该重新挂起 not-smallest 节点而不是 smallest

    3) 为什么要免费NULL

    (treePtr)->item = NULL;
    free(treePtr->item);
    

    【讨论】:

    • 2) 我想是的,你说的重新挂起是什么意思? 3) 这一点意义都没有,我编辑了原始帖子。
    • @Impasse 2) not-smallest 节点应该是 root-node 的左子节点
    • @user3365922 不,他是正确的。非最小的与最小的字符串没有任何共同之处。
    • @VladfromMoscow 你应该删除smallest 节点,在这种情况下树会是什么样子?
    • @user3365922 他没有删除整个节点。他正在删除存储在节点中的字符串本身。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多