Pracuję na wdrożenie Search drzewo AVL. Dotychczas Skończyłem część kodującą i zacząłem testowanie go na błędy. I okazało się, że moje metody rotacji węzłowe są na podsłuchu i na litość boską nie rozumiem w czym problem.
Algorytm działa tak jak powinien na papierze, ale gdy są wykonywane na komputerze, to dobrze ... przecieki węzłów drzewa.
Jest to metoda stosowana do obracania węzeł w lewo: http://pastebin.com/mPHj29Af
bool avl_search_tree::avl_tree_node::rotate_left()
{
if (_right_child != NULL) {
avl_tree_node *new_root = _right_child;
if (_parent != NULL) {
if (_parent->_left_child == this) {
_parent->_left_child = new_root;
} else {
_parent->_right_child = new_root;
}
}
new_root->_parent = _parent;
_parent = new_root;
_right_child = new_root->_left_child;
new_root->_left_child = this;
if (_right_child != NULL) {
_right_child->_parent = this;
}
//update heights
update_height();
new_root->update_height();
return true;
}
return false;
}
W moim metoda wstawiania I skomentował AVL część równoważąca i zamiast po prostu próbuję obrócić nowo wstawionego węzła w lewo. Wynik do wprowadzania liczb całkowitych w kolejności rosnącej: moje drzewo zawiera tylko początkową root (pierwszy węzeł włożona) i wszystkie inne węzły są wyciekły.
Każda pomoc w identyfikacji problemu jest wysoko ceniona jako Zaczynam się zwariować.
Dla przypomnienia: jeśli nie używam żadnych obrotów drzewo nie będzie przeciekać węzły i działa jak normalny niezrównoważonego binarne drzewo poszukiwań (do wkładania i odnośnika).
Edit: W związku z komentarzem AJG85 za dodam uwagi:
Dodałem printf „kontroli” metody destruktora avl_search_tree :: avl_tree_node że będzie drukować wartość klucza (w moim przypadku 32-bitowych liczb całkowitych) przed czyszczeniem i metody insert z avl_search_tree że będzie drukować tylko klucz wstawiony.
Następnie w punkt_wejścia programu I przydzielić avl_search_tree na stercie i dodać do niego klucze w kolejności rosnącej, a następnie usunąć.
Przy włączonej AVL Balancing uzyskać następujący wynik w terminalu:
bool avl_search_tree::insert(const int&) : 1
bool avl_search_tree::insert(const int&) : 2
bool avl_search_tree::insert(const int&) : 3
bool avl_search_tree::insert(const int&) : 4
bool avl_search_tree::insert(const int&) : 5
bool avl_search_tree::insert(const int&) : 6
bool avl_search_tree::insert(const int&) : 7
bool avl_search_tree::insert(const int&) : 8
avl_search_tree::avl_tree_node::~avl_tree_node() : 1
Co oznacza thatall wstawki były udane, ale tylko korzeń został usunięty.
Z AVL Wyważanie wykomentowane działa jak normalny binarne drzewo poszukiwań. Wyjście terminal jest:
bool avl_search_tree::insert(const int&) : 1
bool avl_search_tree::insert(const int&) : 2
bool avl_search_tree::insert(const int&) : 3
bool avl_search_tree::insert(const int&) : 4
bool avl_search_tree::insert(const int&) : 5
bool avl_search_tree::insert(const int&) : 6
bool avl_search_tree::insert(const int&) : 7
bool avl_search_tree::insert(const int&) : 8
avl_search_tree::avl_tree_node::~avl_tree_node() : 1
avl_search_tree::avl_tree_node::~avl_tree_node() : 2
avl_search_tree::avl_tree_node::~avl_tree_node() : 3
avl_search_tree::avl_tree_node::~avl_tree_node() : 4
avl_search_tree::avl_tree_node::~avl_tree_node() : 5
avl_search_tree::avl_tree_node::~avl_tree_node() : 6
avl_search_tree::avl_tree_node::~avl_tree_node() : 7
avl_search_tree::avl_tree_node::~avl_tree_node() : 8
Co oznacza, że wszystko jest prawidłowo czyszczone.
Teraz ... jak ja dochodzę do wniosku, że metody rotacji są problemy? Zgodnie z komentarzem podprogramu bilansującego AVL dodałem linię, która obraca każde nowo wstawionego węzła w lewo. Wynik? Tak samo jak wtedy, gdy podprogram AVL Balancing została włączona.
Oraz dotyczące sposobu update_height (), to nie zmienia strukturę drzewa w jakikolwiek sposób.
Mam nadzieję, że będzie to wyjaśnić.
Edit 2:
Aby wyjaśnić jeszcze kilka rzeczy, jak jest jego destruktor avl_tree_node jest realizowany:
avl_search_tree::avl_tree_node::~avl_tree_node()
{
printf(%s : %d\n, __PRETTY_FUNCTION__, *_key);
if (_left_child != NULL) {
delete _left_child;
}
if (_right_child != NULL) {
delete _right_child;
}
if (_key != NULL) {
delete _key;
}
}
_left_child i _right_child są wskaźnikami do avl_tree_node obiektów przydzielone na stercie.
Edycja 3:
Dzięki AGJ85 za 2 komentarzu znalazłem problem. Obracanie w moich metodach Zapomniałam, że rzeczywiście trzeba zaktualizować drzewa za główny wskaźnik do nowego korzenia gdy korzeń został przesunięty.
Zasadniczo korzeń drzewa był zawsze wskazując pierwszego wstawionego węzła i bez aktualizacji wskaźnika, gdy są potrzebne, by moi Rotate metody wyciek pierwiastek nowe drzewo, które zostało właściwie skonfigurowane w prawo. :)
Dziękuję AGJ85!













