Estoy trabajando en la implementación de un árbol de búsqueda AVL. Hasta el momento he terminado la parte de codificación y he comenzado a probar que para los insectos. Descubrí que están pinchados mis métodos de rotación de nodo y por el amor de dios no puedo entender cuál es el problema.
El algoritmo funciona como debería en el papel pero cuando se ejecuta en una máquina bien ... se escapa nodos del árbol.
Este es el método utilizado para hacer girar un nodo a la izquierda: 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;
}
En mi método de inserción Comenté la AVL equilibrar parte y en su lugar sólo estoy tratando de girar el nodo que acaba de insertar a la izquierda. El resultado de la inserción de números enteros en orden ascendente: mi árbol sólo contiene la raíz de inicio (primer nodo está insertada) y todos los demás nodos se filtraron.
Cualquier ayuda en la identificación del problema es muy apreciada como yo estoy empezando a volverse loco.
Para el registro: si yo no uso ninguna rotación del árbol no se escape nodos y funciona como un árbol binario de búsqueda desequilibrada normal (para la inserción y la búsqueda).
Editar: Debido al comentario de AJG85 voy a añadir las observaciones:
Añadí 'cheques' printf al método destructor de avl_search_tree :: avl_tree_node que imprimirá el valor de la clave (en mi caso enteros de 32 bits) antes de la limpieza y, en el método de inserción de la avl_search_tree que imprimirá la tecla acaba de insertar.
Luego, en punto de entrada del programa asigno un avl_search_tree en el montón y añadir llaves a ella en orden ascendente y luego eliminarlo.
Con AVL Equilibrio habilitado Me da la siguiente salida en el 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
Lo que significa thatall inserciones tuvieron éxito, pero sólo la raíz ha sido eliminado.
Con la AVL El equilibrado comentada funciona como un árbol binario de búsqueda normal. La salida del terminal es:
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
Lo que significa que todo se limpia correctamente.
Ahora ... ¿Cómo he llegado a la conclusión de que los métodos de rotación son los problemas? En el marco del subprograma de equilibrio AVL comentado he añadido una línea que gira cada nodo que acaba de insertar a la izquierda. ¿El resultado? Lo mismo que si la subrutina AVL Equilibrio estaba habilitado.
Y con respecto al método update_height (), no altera la estructura del árbol de ninguna manera.
Espero que esto se aclare.
Edición 2:
Para aclarar algunas cosas más, el suyo es cómo se implementa el destructor avl_tree_node:
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 y _right_child son punteros a avl_tree_node objetos asignados en el montón.
Editar 3:
Gracias al segundo comentario de AGJ85 he encontrado el problema. En mis métodos rotar olvidé que realmente tiene que actualizar puntero de la raíz del árbol de la nueva raíz cada vez que se cambió la raíz.
Básicamente la raíz del árbol siempre estaba apuntando al primer nodo insertado y sin actualizar el puntero cuando sea necesario, rotar mis métodos podrían filtrarse raíz del nuevo árbol que fue realmente configurado derecha. :)
Gracias AGJ85!













