StackOverflowException dans l'algorithme de BST

voix
1

Je suis en train de mettre en œuvre une méthode Contains dans ma classe BSTree qui accepte une valeur, puis vérifier à travers tous les nœuds pour voir si elle est contenue dans l'arbre. Je pense que l'algorithme est correct, mais je ne sais pas pourquoi je continue à obtenir un StackOverflowException au premier instruction if. Des idées?

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
          }
        }        
      }
    }
Créé 10/08/2011 à 04:42
source utilisateur
Dans d'autres langues...                            


3 réponses

voix
0

votre logique est incorrecte. Il ne va pas au retour fausse déclaration.

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
          }
        }        
      }
    }
Créé 10/08/2011 à 04:49
source utilisateur

voix
3

Le problème avec votre code est que vous passez le mauvais nœud dans les appels récursifs. Supposons, par exemple, que votre élément est plus petit que tout dans l'arbre. Ensuite, le premier appel récursif, vous tomberez sur cette déclaration:

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

Cela signifie que vous RECURSE sur la racine , et non l'enfant gauche. Ainsi la prochaine itération, vous constaterez que l'élément est plus petit que l'enfant droite de la racine, et ainsi vous exécuter à nouveau la même déclaration exacte, appelant récursivement la même fonction à plusieurs reprises jusqu'à ce que vous manquez d'espace de pile.

Pour résoudre ce problème, vous devez modifier le code ci-dessus pour lire

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

Cela dit de regarder dans le sous-arbre gauche du noeud courant, pas le nœud racine lui-même. De même, vous aurez besoin de mettre à jour le cas correspondant à la branche droite.

Enfin, pour finir ceci, vous aurez besoin d'ajouter un boîtier de base à votre fonction récursive qui gère le cas où l'arbre est null, que ce soit parce que vous avez marché de l'arbre ou l'arbre était vide pour commencer. Je vais laisser cela comme un exercice. :-)

Créé 10/08/2011 à 04:52
source utilisateur

voix
0

Vous n'avez pas besoin récursivité. Vous pouvez simplement itérer donc vous ne Geta StackOverflow même si vous avez un arbre énorme.

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;
 }
Créé 10/08/2011 à 11:47
source utilisateur

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