【问题标题】:StackOverFlowException in BST algorithmBST 算法中的 StackOverFlowException
【发布时间】:2011-10-23 18:05:31
【问题描述】:

我一直在尝试在我的 BSTree 类中实现一个 Contains 方法,该方法将接受一个值,然后检查所有节点以查看它是否包含在树中。我认为该算法是正确的,但我不知道为什么我在第一个 if 语句中不断收到 StackOverFlowException。有什么想法吗?

public Boolean Contains(T item)
    {
      Node<T> node = root;
      return contains(root, item);
    }



    private Boolean contains(Node<T> node, T item)
    {
      if (item.CompareTo(root.Data) == 0)
      {
        return true;//return 0 if found
      }
      else
      {
        if (item.CompareTo(root.Data) > 0)
        {
          //root = node.Left;
          Node<T> left = root.Left;
          return(contains(root, item));
        }
        else
        {
          if (item.CompareTo(root.Data) < 0)
          {
            //root = node.Right;
            Node<T> right = root.Right;
            return(contains(root, item));
          }
          else
          {
            return false;//return 1 if not found
          }
        }        
      }
    }

【问题讨论】:

  • 我对 Contains() 和其他一些部分感到困惑。为什么将 root 分配给节点,然后使用 root 进行 contains() 调用?该节点的副本从未使用过。看起来您的递归不会在所有情况下都终止(因此 StackOverflowException)。如果你到达一个空叶节点但没有找到匹配项怎么办?
  • @mwd(看起来你的递归不会终止)。什么是解决方案!

标签: c# algorithm exception tree binary-search-tree


【解决方案1】:

您的代码的问题是您将错误的节点传递给递归调用。例如,假设您的元素比树中的所有元素都小。然后在第一次递归调用中,你会遇到这个语句:

Node<T> left = root.Left;
return(contains(root, item));

这意味着你在 root 上递归,而不是左孩子。因此,在下一次迭代中,您会发现该元素小于根的右子元素,因此您将再次执行完全相同的语句,反复递归调用相同的函数,直到用完堆栈空间。

要解决这个问题,您应该将上面的代码更改为阅读

Node<T> left = node.Left;
return(contains(left, item));

这表示查看当前节点的左子树,而不是根节点本身。同样,您需要为正确的分支更新相应的案例。

最后,要完成此操作,您需要在递归函数中添加一个基本情况,以处理树为 null 的情况,因为您已经离开树或树为空首先。我将把它留作练习。 :-)

【讨论】:

    【解决方案2】:

    你的逻辑不正确。它不会去return false语句。

    private Boolean contains(Node<T> node, T item)
        {
          if (item.CompareTo(root.Data) == 0)
          {
            return true;//return 0 if found
          }
          else///if 0 <> 
          {
            if (item.CompareTo(root.Data) > 0)  //if 0<
            {
              //root = node.Left;
              Node<T> left = root.Left;
              return(contains(root, item));
            }
            else  //if 0>
            {
              if (item.CompareTo(root.Data) < 0) if // 0>
              {
                //root = node.Right;
                Node<T> right = root.Right;
                return(contains(root, item));
              }
              else  // this will be not executed ever
              {
                return false;//return 1 if not found
              }
            }        
          }
        }
    

    【讨论】:

      【解决方案3】:

      你不需要递归。你可以迭代,这样即使你有一棵巨大的树,你也不会得到 StackOverflow。

      public Boolean Contains(T item) {
          Node<T> currentNode = root;
      
          while(currentNode != null) { // Or whatever you use to signal that there is no node.
              switch(item.CompareTo(currentNode.Data)) {
                  case -1:
                      currentNode = currentNode.Right;
                      break;
                  case 1:
                      currentNode = currentNode.Left;
                      break;
                  default: // case 0
                      return true;
              }
          }
          return false;
       }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-11-24
        • 1970-01-01
        • 1970-01-01
        • 2012-08-15
        • 2020-03-14
        • 2013-07-24
        • 1970-01-01
        • 2010-09-11
        相关资源
        最近更新 更多