StackOverFlowException w algorytmie BST

głosy
1

I zostały próbuje wdrożyć Zawiera metody do mojej klasy BSTree że przyjmie wartość, a następnie sprawdzić przez wszystkie węzły, aby sprawdzić, czy jest on zawarty w drzewie. Myślę, że algorytm jest poprawny, ale nie wiem dlaczego Wciąż otrzymuję StackOverFlowException na pierwszy if. Jakieś pomysły?

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
          }
        }        
      }
    }
Utwórz 10/08/2011 o 04:42
źródło użytkownik
W innych językach...                            


3 odpowiedzi

głosy
0

Twoja logika jest błędna. Nie pójdzie do powrotnego fałszywego oświadczenia.

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
          }
        }        
      }
    }
Odpowiedział 10/08/2011 o 04:49
źródło użytkownik

głosy
3

Problem z kodem jest to, że jesteś przejazdem w rekurencyjnych wywołań zły węzeł. Załóżmy na przykład, że elementem jest mniejszy niż wszystko w drzewie. Następnie na pierwszym rekurencyjnego wywołania, trafisz to stwierdzenie:

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

Oznacza to, że przeszukanie na korzeniu , a nie lewy dziecięcej. Tak więc na następnej iteracji, przekonasz się, że element jest mniejszy niż prawy dziecka korzenia, a więc będzie wykonać jeszcze raz dokładnie to samo oświadczenie, rekurencyjne wywołanie wielokrotnie tę samą funkcję, dopóki nie zabraknie miejsca stosu.

Aby rozwiązać ten problem, należy zmienić powyższy kod do odczytu

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

To mówi patrzeć w lewym poddrzewie bieżącego węzła, a nie sam węzła głównego. Podobnie, trzeba zaktualizować odpowiednią sprawę do prawej gałęzi.

Na koniec, aby zakończyć ten mecz, trzeba dodać przypadek bazowy do funkcji rekurencyjnej, który obsługuje przypadek, gdy drzewo jest null, albo dlatego, że odszedł drzewo lub drzewo było puste, aby zacząć. Zostawiam to jako ćwiczenie. :-)

Odpowiedział 10/08/2011 o 04:52
źródło użytkownik

głosy
0

Nie trzeba rekursji. Można po prostu iteracyjne więc nie Geta StackOverflow nawet jeśli mają ogromne drzewo.

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;
 }
Odpowiedział 10/08/2011 o 11:47
źródło użytkownik

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