Professional Documents
Culture Documents
Nacional
de Trujillo
EST
RUC
TUR
DOCENTE:
Cruz Florin Iris
FACULTAD:
Ciencias Fsicas y
Matemticas
ESCUELA:
Ing. Informtica II
Ciclo B
INTEGRANTES:
Moreno Cabrera Antony
RBOLES AVL
Kevin
rboles AVL
Un rbol AVL es un rbol binario de bsqueda que cumple con la condicin de que la diferencia
entre las alturas de los subrboles de cada uno de sus nodos es, como mucho 1.
La denominacin de rbol AVL viene dada por los creadores de tal estructura (Adelson-Velskii y
Landis).
Recordamos que un rbol binario de bsqueda es un rbol binario en el cual cada nodo cumple
con que todos los nodos de su subrbol izquierdo son menores que la raz y todos los nodos del
subrbol derecho son mayores que la raz.
Recordamos tambin que el tiempo de las operaciones sobre un rbol binario de bsqueda son
O(log n) promedio, pero el peor caso es O(n), donde n es el nmero de elementos.
La propiedad de equilibrio que debe cumplir un rbol para ser AVL asegura que la profundidad
del rbol sea O(log(n)), por lo que las operaciones sobre estas estructuras no debern recorrer
mucho para hallar el elemento deseado. Como se ver, el tiempo de ejecucin de las
operacines sobre estos rboles es, a lo sumo O(log(n)) en el peor caso, donde n es la cantidad
de elementos del rbol.
Sin embargo, y como era de esperarse, esta misma propiedad de equilibrio de los rboles AVL
implica una dificultad a la hora de insertar o eliminar elementos: estas operaciones pueden no
conservar dicha propiedad.
A modo de ejemplificar esta dificultad, supongamos que al rbol AVL de enteros le queremos
agregar el entero 3. Si lo hacemos con el procedimiento normal de insercin de rboles binarios
de bsqueda el resultado sera el rbol de la siguiente figura el cual ya no cumple con la
condicin de equilibrio de los rboles AVL dado que la altura del subrbol izquierdo es y la del
subrbol derecho es 0.
FE
Estructura de Datos
rboles AVL
Estructura de Datos
rboles AVL
// Selectores
AVLTree *izquierdo (AVLTree * t); //devuelve el subrbol izquierdo de t.
AVLTree *derecho (AVLTree * t); // devuelve el subrbol derecho de t.
int raiz (AVLTree * t); //devuelve el valor de la raz del rbol t. Precondicin: !es_vacio(t)
int altura (AVLTree * t); // devuelve la altura del nodo t en el rbol
// Destructores
void destruir (AVLTree * t, void (*free_dato) (int)); //libera la memoria ocupada por los nodos
del rbol. Si los datos almacenados en cada nodo estn almacenados dinmicamente y se los
quiere liberar tambin, debe pasarse como segundo parmetro una funcin de tipo void func(int
t) que libere la memoria de objetos int. Si los datos no estn almacenados dinmicamente o
simplemente no se los quiere destruir (liberar de memoria), psese como segundo parmetro
NULL. Nota: Funcin Recursiva
ALTURA DE UN NODO
Una funcin para calcular la altura de un nodo puede escribirse recursivamente como:
1.
2.
3.
4.
5.
6.
7.
Queremos que la altura de un rbol que consta de slo un nodo sea 0. Entonces debemos definir
la altura de un rbol vaco como -1. Sin embargo, no podemos darnos el lujo de tener una
funcin cuyo tiempo de ejecucin siempre es O(n) ya que, como dijimos, necesitamos la altura
de un nodo en tiempo constante. Para ello, redefiniremos la funcin de la siguiente manera,
aprovechando el campo altura que ahora tiene cada nodo del rbol.
1.
2.
3.
4.
5.
6.
7.
Importante: Debemos tener mucho cuidado en actualizar el campo altura de cada nodo siempre
que modifiquemos de alguna manera el rbol AVL. As, es importante tener una funcin que nos
permita actualizar la altura de un nodo cualquiera del rbol y cuyo tiempo de ejecucin sea O(1)
en el peor de los casos. A continuacin se lista una tal funcin:
1. Void actualizar_altura (AVLTree * t)
2. {
3. if(!es_vacio(t))
Estructura de Datos
rboles AVL
4. t->altura = max (altura ((t)->izq), altura ((t)->der)) + 1;
5. }
OPERACIONES
Rotaciones
El reequilibrado se produce de abajo hacia arriba sobre los nodos en los que se produce el
desequilibrio. Pueden darse dos casos: rotacin simple o rotacin doble; a su vez ambos
casos pueden ser hacia la derecha o hacia la izquierda.
RSI
RSD
RDI
RDD
Insercin
Extraccin
Bsqueda
ROTACIONES SIMPLES
Veremos a continuacin una operacin sencilla sobre un rbol binario de bsqueda que conserva
el orden en sus nodos y que nos ayudar a restaurar la propiedad de equilibrio de un rbol AVL
al efectuar operaciones sobre el mismo que puedan perturbarla.
Estructura de Datos
rboles AVL
rbol luego de la
rotacin simple
Veamos un ejemplo
concreto.
Deseamos
insertar el nmero 3
en el rbol de enteros de
Figura 1. La insercin se muestra punteada en Figura 2. Sin embargo, como puede verse, la
insercin a provocado la prdida de la propiedad de equilibrio del rbol ya que dicha propiedad
no se cumple en el nodo marcado con rojo. Qu hacemos para recomponer dicha propiedad?
Simplemente realizamos una rotacin simple. En este caso se dice que la rotacin es izquierda
ya que la "prdida de equilibrio se produce hacia la izquierda. En Figure 3 puede verse el rbol
luego de la rotacin: la propiedad de equilibrio ha sido restablecida. Como mostramos atrs, la
rotacin conserva el orden entre los nodos, por lo que podemos afirmar que este ltimo rbol si
es AVL.
Figura 1. rbol
Avl2. rbol luego de la insercin. Prdida de la propiedad de equilibrio marcada con rojo
Figura
Estructura de Datos
rboles AVL
Como podemos observar, el resultado luego de la rotacin es un rbol AVL: posee tanto el rden
correcto de un rbol de bsqueda entre sus nodos y la propiedad de equilibrio. En este caso el
"desequilibrio" en el rbol con raz 5 era enteramente hacia la izquierda y por lo tanto, como ya
dijimos, la rotacin efectuada se denomina rotacin simple izquierda.
En el caso de un "desequilibrio" hacia la derecha, la rotacin es anloga y se denomina rotacin
simple derecha. En la siguiente figura se ven dos rboles: el primero tiene un "desequilibrio
hacia la derecha" marcado en rojo y el segundo es el resultado de aplicar una rotacin simple
derecha.
Estructura de Datos
rboles AVL
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
(1)
Estructura de Datos
rboles AVL
En estos casos se aplica otro tipo de rotacin denominado rotacin doble la cual, anlogamente
a la rotacin simple, puede ser izquierda o derecha segn el caso. En realidad, la rotacin doble
constar de dos rotaciones simples.
El caso general de la rotacin doble izquierda en un rbol AVL se puede observar aqu:
La rotacin doble derecha es el proceso inverso a la rotacin doble izquierda. Dado que, como
vimos, una rotacin doble es en realidad dos rotaciones simples, podemos implementar la
funcin para la rotacin doble tan slo utilizando rotar_s vista anteriormente lo cual se hace a
continuacin:
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
Estructura de Datos
rboles AVL
12.
rotar_s (&(*t)->der, true);
13.
rotar_s (t, false);
14.
}
15.
// la actualizacin de las alturas se realiza en las rotaciones simples
16. }
(1) Declaracin de la funcin rotar_d(); debera ir en un archivo de cabecera.
(2) Los parmetros de rotar_d() son anlogos a los de rotar_s()
BALANCE DEL ARBOL
Como se mostr anteriormente, cada vez que se modifique el rbol ( agreguen o eliminen
elementos) corremos el riesgo de que pierda su propiedad de equilibrio en alguno de sus nodos,
la cual debe conservarse si queremos obtener tiempos de ejecucin de orden O(log(n)) en el
peor de los casos.
La idea general que se utiliza en esta implementacin de rboles AVL para implementar los
algoritmos de insercin y de eliminacin de nodos sobre un AVL es la siguiente:
Efectuar los algoritmos de igual forma que en los rboles binarios de bsqueda pero
En cada recursin ir actualizando las alturas y rebalanceando el rbol en caso de que sea
necesario.
Lo que nos falta es una funcin que detecte un "desequilibrio" en un nodo dado del rbol y por
medio de un nmero finito de rotaciones lo equilibre.
En las secciones anteriores hemos ya descripto a grandes rasgos cul rotacin usar en cada caso
de desequilibrio. Esperamos que en el cdigo siguiente el lector pueda formalizar tales ideas.
Estructura de Datos
10
rboles AVL
22.
// desequilibrio doble hacia la izquierda
23.
rotar_d (t, false);
24.
}
25.
}
26. }
(1) Declaracin de la funcin balancear(). Esta declaracin junto con el comentario que le
sigue deberan estar en un archivo de cabecera usado para la interfaz del tipoabstracto
de dato rbol avl con el usuario-programador.
(2) Como dice en el comentario de la funcin, slo se contemplarn aquellos desequilibrios
cuya diferencia entre alturas es hasta 2.
(3) Sabiendo que en el nodo al que apunta *t hay un desequilibrio hacia la izquierda (de
diferencia de alturas 2), debemos averiguar qu clase de rotacin aplicar. En la siguiente
figura se explica grficamente a dnde apuntan las variables de la funcin en un rbol
genrico.
Decidiendo qu clase de rotacin aplicar para solucionar desequilibrio en el nodo.
Como
verse en el
nos
decidimos
rotacin
izquierda
subrbol
pesado de
es
el
o por una
doble
si
el
ms
(*t)->izq es el derecho.
puede
cdigo,
por una
simple
si
el
ms
(*t)->izq
izquierdo
rotacin
izquierda
subrbol
pesado de
INSERCION
Implementaremos la insercin de elementos en un rbol AVL de forma anloga a cmo lo
haramos para rboles binarios de bsqueda salvo que en cada recursin del algoritmo
verificaremos y corregiremos el equilibrio del rbol. Tambin es importante ir actualizando las
alturas de cada nodo en cada recursin dado que las rotaciones, insercines y eliminaciones
pueden modificarlas.
Dado que ya vimos funciones tanto para balancear un rbol y para actualizar la altura de un
nodo (ambas de tiempo de ejecucin constante), estamos listos para implementar el algoritmo
de insercin. Esperamos que sea intuitivo.
11
rboles AVL
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
ELIMINACION
La estrategia para disear el algoritmo de eliminacin sobre rboles AVL es la misma que para
la insercin: Se utiliza el mismo algoritmo que sobre rboles binarios de bsqueda, pero en cada
recursin se detectan y corrijen errores por medio de balancear() y se actualiza la altura del
nodo actual.
Recordamos un poco la idea del algoritmo de eliminacin sobre rboles binarios de bsqueda.
Primero se recorre el rbol para detectar el nodo a eliminar. Una vez hecho esto hay tres casos a
diferenciar por su complejidad:
Si dicho nodo es una hoja procedemos a eliminarlos de inmediato, sin ms.
Si dicho nodo tiene un slo hijo, el nodo puede eliminarse despus de ajustar un apuntador del
padre para saltar el nodo.
Estructura de Datos
12
rboles AVL
2. //elimina x del rbol en un tiempo O(log(n)) peor caso. Precondicin: existe un nodo
con valor x en el rbolt.
3. int eliminar_min (AVLTree ** t);
4. // Funcin auxiliar a eliminar(). Elimina el menor nodo del rbol *t devolviendo su
contenido (el cual no se libera de memoria). Se actualizan las alturas de los nodos.
Precondicin: !es_vacio(*t)
5. void eliminar (AVLTree ** t, int x)
6. {
7.
AVLTree *aux;
8.
if (x < raiz (*t))
9.
eliminar (&(*t)->izq, x);
10. else if (x > raiz (*t))
11.
eliminar (&(*t)->der, x);
12.
else //coincidencia
13.
{
14.
if (es_vacio (izquierdo (*t)) && es_vacio (derecho (*t)))
15.
{//es una hoja
16.
free (*t);
17.
(*t) = vacio();
18.
}
19.
else if (es_vacio (izquierdo (*t)))
20.
{//subrbol izquierdo vacio
21.
aux = (*t);
22.
(*t) = (*t)->der;
23.
free (aux);
24.
}
25.
else if (es_vacio (derecho (*t)))
26.
{// subrbol derecho vacio
27.
aux = (*t);
28.
(*t) = (*t)->izq;
29.
free (aux);
30.
}
31.
else // caso ms complicado
32.
{
33.
(*t)->dato = eliminar_min (&(*t)->der);
34.
}
35.
}
36.
balancear (t);
37.
actualizar_altura (*t);
38. }
39.
40. int eliminar_min (AVLTree ** t)
41. {
42. if (es_vacio (*t))
43. {
44.
fprintf (stderr, "No se respeta precondicin de eliminar_min()\n");
45.
exit(0);
46.
}
47.
else
48. {
49.
if (!es_vacio (izquierdo (*t)))
50.
{
51.
int x = eliminar_min (&(*t)->izq);
52.
balancear (t);
Estructura de Datos
13
rboles AVL
53.
actualizar_altura (*t);
54.
return x;
55.
}
56.
else
57.
{
58.
AVLTree *aux = (*t);
59.
int x = raiz (aux);
60.
*t = derecho (*t);
61.
free (aux);
62.
balancear (t);
63.
actualizar_altura (*t);
64.
return x;
65.
}
66.
}
67. }
Estructura de Datos
14