【问题标题】:binary tree recursively search c code [not Binary Search Tree]二叉树递归搜索c代码[不是二叉搜索树]
【发布时间】:2013-04-14 06:51:43
【问题描述】:

我的代码的问题是,当搜索左子值时,由于递归级别,它会返回并检查右子值。并且返回不正确。我找不到克服它的方法。

node * search(node *ptr,int key)
{
    if(ptr->data==key)
        return ptr;
    else
    {
        if(ptr->lchild!='\0')
            search(ptr->lchild,key);
        else
            return '\0';
        if(ptr->rchild!='\0')
            search(ptr->rchild,key);
        else
            return '\0';
    }
}

【问题讨论】:

  • 请给出node的声明。您可能会编码return search(ptr->lchild,key);,但我不明白您的代码想要做什么。你在编码什么样的树?树是如何构造的?它的不变量是什么?
  • @BasileStarynkevitch 这只是一个未排序的二叉树。有足够的关于node的数据
  • @BasileStarynkevitch 它只是一个带有两个子链接指针和一个整数数据的简单节点......而且它是未排序的,因为它只是一个二叉树......不是二叉搜索树

标签: c search recursion binary-tree


【解决方案1】:

大概是这样

node * search(node *ptr,int key)
{
    node *pwk;
    if(ptr == NULL) return NULL;
    if(ptr->data==key)
        return ptr;
    if(NULL!=(pwk=search(ptr->lchild,key)))
        return pwk;
    if(NULL!=(pwk=search(ptr->rchild,key)))// or return search(ptr->rchild,key);
        return pwk;
    return NULL;
}

【讨论】:

    【解决方案2】:

    没错。试试这个:

    node * search(node *ptr,int key)
    {
        if(ptr->data==key)
            return ptr;
        else
        {
            node *current = NULL;
            if(ptr->lchild != NULL)
                current = search(ptr->lchild,key);
    
            if(current == NULL) /* not found in the left subtree */
            {
                if(ptr->rchild != NULL)
                    current = search(ptr->rchild,key);
            }
            return current;
        }
    }
    

    【讨论】:

      【解决方案3】:
      Node *search(Node *ptr, int key)
      {
          Node *found;
          if ( !ptr || ptr->data == key) return ptr;
      
          found = search(ptr->lchild, key);
      
          return (found) ? found : search(ptr->rchild, key);
      }
      

      注意:||?: 都使用 short circuit 评估,这使我可以将 if(...) 条件的数量减少到一个。

      更新:如果允许我们使用“残缺的三元”操作符 gnu-extension,我们也可以避免变量:

      Node *search2(Node *ptr, int key)
      {
          if ( !ptr || ptr->data == key) return ptr;
      
          return search2(ptr->lchild, key) ?: search2(ptr->rchild, key);
      }
      

      添加另一个三元会完全删除if(...)

      Node *search3(Node *ptr, int key)
      {
          return ( !ptr || ptr->data == key) 
              ? ptr
              : search3(ptr->lchild, key) ?: search3(ptr->rchild, key);
      }
      

      【讨论】:

      • 只是想知道,为什么?为什么要如此努力地删除一个完全有效的 if 语句并最终得到深奥且不可移植的“残缺三元”?
      • 原因很简单:简单。更少的 {lines,variables} := 更少的出错机会。并且:我也不喜欢扩展,但是这个例子清楚地表明存在残缺三元的情况。它甚至可能包含在下一个 C 标准中。
      • 简单!= 更少的代码。这非常紧凑:for(unsigned i = 0; i < 20; i++) a[i & (unsigned)(-2)] = i; 但完全不可读且容易出错。
      • 另一个原因是可验证性。在我(和@BLUEPIXY 的)中,在做任何其他事情之前回答 ptr 为 NULL 的函数测试。您(和所有其他人)在两个地方(在递归调用之前)检查它,但在使用 NULL ptr 参数调用时仍然会失败。
      • 哦,拜托!那很蹩脚。我的回答并没有假装是杰作,它只是一个草图。我的问题非常具体,与无效检查无关
      【解决方案4】:
      node * search(node *ptr,int key)
      {
          Node * p;
      
          // Found the key, return the pointer to the node
          if (ptr->data==key)
              return ptr;
      
          if (ptr->lchild != NULL)
          {
              p = search(ptr->lchild,key);
              // Found the key, return the pointer to the node
              if(p != NULL)
                  return p;
          }
          // Didn't find it in the lchild, so search rchild
          if (ptr->rchild != NULL)
          {
              p = search(ptr->rchild,key);
              // Found the key, return the pointer to the node
              if(p != NULL)
                  return p;
          }
      
          // Not found in left or right child, return NULL
          return NULL;
      }
      

      在这种情况下避免使用\0\0 用于空字符。 NULL 用于空指针。虽然两者通常都是 0,但最好使用 NULL 作为指针。检查此问题以获取更多详细信息 - What is the difference between NULL, '\0' and 0

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-01-02
        • 2015-06-16
        • 1970-01-01
        • 1970-01-01
        • 2021-07-03
        • 2019-04-17
        • 1970-01-01
        相关资源
        最近更新 更多