Je travaille sur la mise en œuvre d'un arbre AVL de recherche. Jusqu'à présent, j'ai terminé la partie codante et j'ai commencé à tester pour les bugs. J'ai découvert que mes méthodes de rotation des noeuds sont mis sur écoute et pour l'amour de Dieu, je ne comprends pas quel est le problème.
L'algorithme fonctionne comme il se doit sur le papier, mais lorsqu'il est exécuté sur une machine bien ... fuites nœuds d'arbres.
Ceci est la méthode utilisée pour faire tourner un noeud vers la gauche: 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;
}
Dans ma méthode d'insertion je commentais la partie d'équilibrage AVL et au lieu que je suis juste essayer de faire tourner le nouveau nœud inséré à gauche. Le résultat pour l'insertion des nombres entiers dans l'ordre croissant: mon arbre ne contient que la racine initial (premier noeud inséré) et tous les autres noeuds sont divulgués.
Toute aide à identifier le problème est très apprécié que je commence à devenir fou.
Pour mémoire: si je n'utilise pas la rotation de l'arbre ne fuira pas les nœuds et il fonctionne comme un arbre de recherche binaire asymétrique normale (pour l'insertion et recherche).
Edit: En raison du commentaire de AJG85 Je vais ajouter les observations:
J'ai ajouté des « contrôles » printf à la méthode destructor de avl_search_tree :: avl_tree_node qui imprimera la valeur de clé (dans mon cas des entiers 32 bits) avant le nettoyage et la méthode d'insertion du avl_search_tree qui imprimera la clé juste insérée.
Ensuite, dans le point d'entrée du programme que j'allouer un avl_search_tree sur le tas et ajouter des clés à elle dans l'ordre croissant, puis le supprimer.
Avec AVL équilibrage activé, je reçois la sortie suivante dans le terminal:
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
Ce qui signifie que des insertions ont réussi quetous mais seulement la racine a été supprimé.
Avec l'équilibrage AVL commenté cela fonctionne comme un arbre de recherche binaire normal. La borne de sortie est la suivante:
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
Ce qui signifie que tout est correctement nettoyé.
Maintenant ... Comment suis-je arrivé à la conclusion que les méthodes de rotation sont les enjeux? Dans le cadre du sous-programme d'équilibrage de AVL a commenté J'ai ajouté une ligne qui tourne chaque nœud nouvellement inséré à gauche. Le résultat? La même chose que si le sous-programme d'équilibrage AVL a été activé.
Et en ce qui concerne la méthode update_height (), il ne modifie pas la structure de l'arbre de quelque façon.
J'espère que cela le préciser.
Edit 2:
Pour clarifier les choses encore plus, comment le son est destructor de avl_tree_node est mis en œuvre:
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 et _right_child sont des pointeurs vers des objets avl_tree_node alloués sur le tas.
Edit 3:
Merci au 2 commentaire de AGJ85 Je trouve la question. Dans mes méthodes rotate j'ai oublié que j'ai fait mettre à jour le pointeur de la racine de l'arbre à la nouvelle racine à chaque fois que la racine a été déplacée.
Fondamentalement, la racine de l'arbre a toujours été dirigée vers le premier noeud inséré et sans mettre à jour le pointeur en cas de besoin, mes méthodes rotate seraient fuir la racine du nouvel arbre qui a été configuré en fait à droite. :)
Merci AGJ85!













