StackOverflowException в алгоритме BST

голоса
1

Я пытался реализовать содержит метод в моем классе BSTree, который будет принимать значение, а затем проверить через все узлы, чтобы увидеть, если он содержится в дереве. Я думаю, что алгоритм является правильным, но я не знаю, почему я продолжаю получать 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
          }
        }        
      }
    }
Задан 10/08/2011 в 04:42
источник пользователем
На других языках...                            


3 ответов

голоса
0

логика неверна. Он не будет идти к возвратному ложному утверждению.

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
          }
        }        
      }
    }
Ответил 10/08/2011 в 04:49
источник пользователем

голоса
3

Проблема с кодом является то, что вы передаете неправильный узел в рекурсивные вызовы. Предположим, например, что ваш элемент меньше, чем все в дереве. Тогда на первый рекурсивный вызов, вы поразите это заявление:

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

Это означает , что вы рекурсию на корне , а не слева ребенка. Таким образом , на следующей итерации, вы увидите , что элемент меньше правый потомок корня, и поэтому вы будете выполнять точно такие же заявление снова, рекурсивно вызывая ту же функцию несколько раз , пока не кончится стека.

Чтобы исправить это, вы должны изменить код выше, чтобы прочитать

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

Это говорит о том, чтобы посмотреть в левом поддереве текущего узла, а не сам корень узла. Кроме того, вам необходимо обновить соответствующий случай для правой ветви.

Наконец, чтобы закончить эту опцию, вам нужно добавить базовый вариант для вашей рекурсивной функции , которая обрабатывает случай , когда дерево null, либо потому , что вы ушли от дерева или дерево было пустым , чтобы начать с. Я оставлю это упражнение. :-)

Ответил 10/08/2011 в 04:52
источник пользователем

голоса
0

Вам не нужно рекурсии. Вы можете просто перебирать, так что вы не Гета 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;
 }
Ответил 10/08/2011 в 11:47
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more