1 Capítulo 11 Árboles binarios balanceados de búsqueda. AVL. El alto de un árbol es el largo de la trayectoria más larga de una hoja hasta la raíz. Adel'son-Vel'skii y Landis (1962) definieron árboles AVL en los cuales, para cada nodo, el alto del subárbol derecho difiere del alto del subárbol izquierdo a lo más en uno. El desarrollo del algoritmo muestra la necesidad de un análisis exhaustivo de los diferentes casos que se presentan. Dicho análisis facilita la posterior codificación. 11.1 Análisis de complejidad. Se define el factor de balance como el alto del subárbol derecho menos el alto del subárbol izquierdo. Entonces en un árbol AVL, todos los nodos cumplen la propiedad de tener valores del factor de balance iguales a: -1, 0, ó +1. Sea nh el mínimo número de nodos en un árbol AVL de altura h dada, que se encuentra en su peor caso de desbalance, si se agrega un nodo, tal que la nueva altura sea (h+1), dejan de ser AVL. Los siguientes diagramas ilustran dichos árboles, denominados de Fibonacci, y los factores de balance de sus nodos, para alturas 0, 1 y 2. Se muestran todos los casos, separados por un eje de simetría; a la derecha del eje se muestran los desbalanceados por la derecha; y a la izquierda los desbalanceados por la izquierda. Las imágenes en ambos lados del eje se obtienen como imágenes especulares de las del otro lado. Lo que se desea encontrar es la altura máxima h de todos los árboles balanceados de n nodos. Para resolver esto se da una altura h determinada y se intenta construir árboles balanceados AVL con el mínimo número de nodos, éstos son los árboles de Fibonacci. Profesor Leopoldo Silva Bijit 20-01-2010 2 Estructuras de Datos y Algoritmos n0 = 1 0 n1 = 2 -1 1 h=1 0 0 Figura 11.1 Árboles Fibonacci AVL, con alturas 0, 1. n2 = 4 -1 -1 1 -1 0 1 1 0 0 0 0 0 0 1 -1 0 Figura 11.1.a. Árboles Fibonacci AVL, con altura 2. Se cumple que: n2 = n1 + n0 + 1 Se pueden generar 4 árboles de Fibonacci con altura dos. Existen adicionalmente varios árboles AVL de altura dos (los con 5, 6, y 7 nodos) pero se consideran “más balanceados” que los de Fibonacci. Para construir el árbol de Fibonacci de altura h, a la raíz se agrega un subárbol de altura (h-1) y otro de altura (h-2). La Figura 11.2 ilustra un ejemplo, de los 16 posibles, de la generación de un árbol de Fibonacci de altura 3, mediante dos subárboles de altura 1 y 2. n3 = 7 Se tiene: n3 = n2 + n1 + 1 1 1 1 0 0 h=3 1 0 Figura 11.2 Ejemplo árbol AVL Fibonacci, con altura 3. Se destaca el hecho de que estos árboles son el peor caso: logran máxima altura, con el mínimo número de nodos. Profesor Leopoldo Silva Bijit 20-01-2010 Árboles balanceados AVL 3 n4 = 12 Se tiene n4 = n3 + n2 + 1 Como ejemplo de árbol con altura 4, a la raíz se agrega por la derecha un árbol de Fibonacci de altura 3, y por la izquierda uno de altura 2, resulta la Figura 11.3. 1 1 1 0 1 1 0_ 1 1 0 0 0 Figura 11.3 Árbol AVL Fibonacci, con altura 4. Mediante inducción puede demostrarse que en general, se tiene la recurrencia: nh nh nh 1 1 con n0 1 y n1 2 2 Lo cual implica que un árbol AVL está formado por dos subárboles AVL. La secuencia generada es: 1, 2, 4, 7, 12, 20, 33, 54… para h=0, 1, 2…. Empleando el siguiente comando Maple, se puede obtener la solución de la recurrencia: > n[h]:= rsolve( { n(h) = n(h-1) + n(h-2) + 1, n(0)=1,n(1)=2}, n(h)); El término general de la serie n(h) es: 1 n h := 2 5 5 1 5 5 2 1 5 2 1 1 1 5 5 5 1 2 1 h 1 1 h 1 5 5 2 5 5 2 1 1 5 5 1 h 1 1 h 1 5 5 Evaluado numéricamente: n(h) 1.894427191(1.618033988)h +.1055728091(-.6180339886)h 1 El segundo término tiende a cero, según muestra la secuencia: > seq( evalf(subs( h =j, .1055728091*(-.6180339886)^h)), j = 0..6); Profesor Leopoldo Silva Bijit 20-01-2010 4 Estructuras de Datos y Algoritmos .1055728091 , -.06524758430 , .04032522477 , -.02492235950 , .01540286525 , -.009519494246 , .005883370999 Finalmente, el número de nodos en función de la altura en un árbol de Fibonacci, resulta: n(h) 1.894427191(1.618033988)h El comando solve permite despejar h, en términos de n. > solve(n=1.894427191*1.618033988^h,h); h (n)= 2.078086923 ln ( .5278640450 n ) Para acotar por arriba, se desea encontrar el valor de la constante c que satisface: c*ln(n)/ln(2)=2.078086923*ln(.5278640450*n) Resulta: ln ( .5278640450 n ) ln ( n ) c = 1.440420092 El factor que depende de n, tiende a uno: c= lim n 1.440420092 ln ( .5278640450 ln ( n ) n) 1.440420092 Lo que también se aprecia en la gráfica: Figura 11.4 Cota AVL en función de n. Finalmente la altura en un árbol AVL queda acotada por: 1.440420092*log(n) > h(avl) > h(bst) Donde h(bst) es la altura de un árbol de búsqueda binario completamente balanceado: h(bst) = log(n+1) Profesor Leopoldo Silva Bijit 20-01-2010 Árboles balanceados AVL Lo cual demuestra que: 5 h(avl) = (log(n)) h=1,44..log(n) altura AVL altura BST Figura 11.5 Complejidad de la altura de un árbol AVL. La siguiente gráfica muestra la diferencia de altura del árbol AVL, respecto de uno perfectamente balanceado, en función de n. Es decir la gráfica del cuociente: 2, 07808ln(0,527864n) log 2 (n) Figura 11.6 Alargue de altura árbol AVL, respecto de perfectamente balanceado Notar que para árboles con menos de 7000 nodos, la altura sólo se alarga en cuatro. Otra forma de encontrar la solución de la recurrencia para n(h), es relacionarla con la secuencia de Fibonacci, para la cual se conoce la solución. La relación para la recurrencia de Fibonacci es: F(i) = F(i – 1) + F(i – 2), F(0) = 0, F(1) = 1 La cual genera: 0, 1, 1, 2, 3, 5, 8, 13, … para i=0, 1, 2…. En el Ejemplo 4.6, se obtuvo, la solución: Profesor Leopoldo Silva Bijit 20-01-2010 6 Estructuras de Datos y Algoritmos 1 1 5 n ( ) 2 5 F ( n) Empleando: 1 5 2 1 1 5 n ( ) 2 5 1 1, 61803.. se tiene que: 1 5 2 . Donde es la razón áurea. C AC = AB A B Figura 11.6.a. Razón áurea . Reemplazando en F(n), n por h, y empleando , se obtiene: F ( h) 1 ( )h 5 1 (1 5 1 ( )h 5 )h Observando las dos secuencias de números que generan n(h) y F(h), se encuentra: h n(h) F(h) F(h+3) 0 1 0 2 1 2 1 3 2 4 1 5 3 4 5 6 7 7 12 20 33 54 2 3 5 8 13 8 13 21 34 55 Entonces, se tiene: n(h) = F(h + 3) – 1. En forma aproximada, se tiene la solución para n(h): n( h) 1 5 h 3 1 1 5 3 h 3 h 5 (1,894413.) h Resultado igual, al obtenido antes. 11.2. Análisis de la inserción. La función de inserción debe ser modificada para mantener la propiedad de árbol AVL. Existen inserciones que sólo implican recalcular los factores de balance, ya que el árbol sigue siendo AVL. Por ejemplo las dos inserciones siguientes, en la Figura 11.7. izquierda, sólo modifican los factores de balance de algunos nodos ancestros del insertado, que están en la trayectoria del recién insertado hacia la raíz. Profesor Leopoldo Silva Bijit 20-01-2010 Árboles balanceados AVL 7 recalculados recalculado 1 1 1 1 0 1 1 0_ 0 1 0 1 1 0 1 0 0 1 0_ 0 1 1 0 0 0 0 insertados Figura 11.7 Inserciones que sólo requieren recalcular factor de balance. 11.2.1. Detención de revisión en ascenso. a) Al insertar por la izquierda, y en el proceso de ascenso, por la trayectoria desde el nodo recién insertado hacia la raíz, revisando los factores de balance, si se llega a un nodo con factor uno, basta corregir el factor de ese nodo (quedando éste en 0) y no es preciso seguir corrigiendo en el ascenso. Esto debido a que ese nodo no cambiará su altura; estaba en h y queda en h. La figura 11.8 izquierda, ilustra una situación general antes de la inserción por la izquierda; la figura 11.8 derecha, muestra después de la inserción y de la corrección del factor de balance. h h -1 A A 1 0 h h detener h Figura 11.8 Detención de revisión en ascenso. Caso a. 11.2.2. Continuar revisando factores de balance en ascenso. b) Al insertar por la izquierda, y en el proceso de ascenso de revisión de los factores de balance, si se llega a un nodo con factor cero, debe corregirse el factor de ese nodo (quedando éste en menos uno) y es preciso seguir el ascenso. Esto debido a que ese nodo cambió su altura; estaba en h y queda en h+1. Profesor Leopoldo Silva Bijit 20-01-2010 8 Estructuras de Datos y Algoritmos A A -1 continuar 0 h+1 h h h Figura 11.9 Continuar revisión en ascenso. Caso b. La Figura 11.9, a la izquierda, ilustra la situación antes de la inserción por la izquierda; la figura a la derecha muestra después de la inserción y de la corrección del factor de balance. Pero la inserción deja el subárbol cumpliendo la propiedad AVL. Existen dos casos adicionales, que corresponden a inserciones por la derecha, y pueden visualizarse con las imágenes especulares de las mostradas. 11.2.3. Casos que producen desbalances. Otras inserciones producen desbalances que dejan al subárbol no AVL. Para encontrar en qué situaciones se producen desbalances que rompan la propiedad AVL, basaremos nuestro análisis en el siguiente subárbol AVL, al cual si se le inserta un nodo en el subárbol derecho, quedará no AVL. Dada la estructura de un árbol AVL, el cual está formado por subárboles AVL, se analiza un árbol AVL de altura dos, pero el análisis es válido para cualquier subárbol AVL. Se escoge un caso sencillo para extraer de él, el caso general: 1 0 0 0 0 Figura 11.10 Árbol AVL, para analizar pérdida de propiedad AVL. Trataremos de insertar en posiciones que desbalanceen el árbol, notando que se deben recalcular los factores de balance, a través de la trayectoria desde el nodo insertado hacia la raíz, y si aparece uno con factor 2, se pierde la propiedad AVL. 11.2.3.1. Inserción externa por la derecha. c) Si se inserta nodo F, en la rama externa más larga del subárbol derecho: La relación de orden del árbol binario es: A<B<C<D<E<F Profesor Leopoldo Silva Bijit 20-01-2010 Árboles balanceados AVL 9 2 0 B A 1 D C 0 E 1 0 F Figura 11.11 Árbol no AVL, después de inserción externa por la derecha. Se trata igual el caso: F<E. Inserciones de nodos con valores menores que B, mejoran los factores de balance, mantienen la propiedad AVL, y no existe necesidad de corregir. Han sido tratados en los casos a y b. Se detecta la pérdida de propiedad AVL, para este caso, cuando el factor de balance de un nodo recalculado después de la inserción es +2, y el factor de balance del hijo derecho de éste es positivo. 11.2.3.2. Inserción interna por la derecha. d) Si se inserta nodo D, en la rama interna más larga del subárbol derecho. Con orden: A<B<C<D<E<F 2 0 B A -1 1 E C 0 0 F D Figura 11.12 Árbol no AVL, después de inserción interna por la derecha. Se trata igual el caso D<C. Inserciones para nodos con valores menores que B, mejoran los factores de balance, y no existe necesidad de corregir. Esta situación se detecta cuando el factor de balance de un nodo es +2, y el factor de balance del hijo derecho de éste es negativo. 11.3.4. Rotaciones para mantener propiedad AVL. Se analizan correcciones a los casos c y d, para mantener la propiedad AVL: El caso c) requiere una reestructuración de los nodos para mantener la propiedad AVL. Manteniendo la relación de orden: A<B<C<D<E<F, se denomina rotación simple a la izquierda, la que deja al subárbol, según: Profesor Leopoldo Silva Bijit 20-01-2010 10 Estructuras de Datos y Algoritmos 0 0 0 A D B 1 0 E 0 C F Figura 11.13 Árbol AVL de Figura 11.11, después de rotación simple a la izquierda. El caso d) de la Figura 11.12, también requiere reestructurar para mantener el árbol con la propiedad AVL. Se corrige con una doble rotación. Primero una a la derecha, que hace ascender C (la situación después de esta rotación, se muestra en la parte izquierda de la Figura 11.14) y luego otra a la izquierda, que hace ascender C hasta la raíz, después de la cual se muestra en la Figura 11.14 a la derecha. 2 0 A B 2 0 C 0 -1 E 0 0 D 0 F A C B 0 0 D E 0 F Figura 11.14 Árbol AVL de la figura 11.12, después de doble rotación. En ambas se conserva la relación de orden: A<B<C<D<E<F Existen dos casos adicionales, que corresponden inserciones por la izquierda, y pueden visualizarse con las imágenes especulares de las mostradas. 11.3.4.1. Corrección con rotación simple en inserción. Se puede generalizar, el caso c) con el diagrama de la Figura 11.15. La figura a la izquierda ilustra la situación antes de agregar un nodo en el subárbol derecho de B. La figura al centro muestra el árbol desbalanceado, no AVL. A la derecha se muestra después de una rotación simple a la izquierda, la cual mejora el balance y genera un árbol AVL. Profesor Leopoldo Silva Bijit 20-01-2010 Árboles balanceados AVL 11 A A 1 B 0 2 B A B 1 0 h h positivo h h h 0 h+1 h h+1 h Figura 11.15 Generalización de caso c). Rotación simple. La rotación a la derecha es la imagen especular de las figuras. Sólo se afectan los factores de balance del trayecto ascendente desde el nodo insertado hacia la raíz. 11.3.4.2. Corrección con rotación doble en inserción. El caso d) también se puede generalizar. Si se agrega nodo en el subárbol izquierdo o derecho del nodo B , Figura 11.16 izquierda, se producirán cambios en los factores de balance, desde el nodo insertado hacia la raíz. Ocasionando el desbalance que se muestra en la figura a la derecha, el árbol no es AVL. A A 1 2 negativo C C -1 0 B -1 B 0 h h-1 h h h h h-1 h-1 Figura 11.16 Generalización de caso d). Lo cual se corrige, con una rotación a la derecha, que hace ascender B , Figura 11.17 izquierda, y luego otra a la izquierda para llevar B a la raíz del subárbol, produciendo un árbol AVL. Profesor Leopoldo Silva Bijit 20-01-2010 12 Estructuras de Datos y Algoritmos A B 0 2 B A 1 C 0 C 1 1 h h h h h-1 h-1 h h Figura 11.17 Generalización de caso d). Doble rotación. Del análisis anterior, el algoritmo de inserción, debe implementar la rotación simple a la derecha y la rotación simple a la izquierda. Observando las correcciones después de las rotaciones, se concluye que no es necesario seguir revisando los factores de balance de los nodos superiores a la raíz del subárbol que originalmente produjo la necesidad de balancear (el que llegó a +2 ó -2), ya que éste queda con factor de balance 0. El alto de ese nodo es (h+1), antes y después de la inserción y las correcciones. 11.3. Análisis del descarte de un nodo. Se descarta en forma similar a un árbol binario. Sin embargo, debido a la propiedad AVL, si el nodo a descartar tiene un solo subárbol (derecho o izquierdo), ese subárbol debe ser una hoja. Si tiene dos subárboles, de acuerdo al factor de balance se descarta el nodo que mejore el balance. Luego del descarte, debe ascenderse para mantener los factores de balance de la trayectoria hacia la raíz, se pueden presentar varios casos. Debido a la simetría sólo se analizan casos de descarte por la izquierda, la solución para descartes por la derecha, se obtiene mediante imágenes especulares. 11.3.1. Detención de la revisión de los factores de balance en el descarte. a) Al descartar por la izquierda, y en el proceso de ascenso de revisión de los factores de balance, si se llega a un nodo con factor cero, basta corregir el factor de ese nodo (quedando éste en +1) y no es preciso seguir el ascenso. Esto debido a que ese nodo no cambiará su altura; estaba en h y queda en h. Profesor Leopoldo Silva Bijit 20-01-2010 Árboles balanceados AVL h 13 A A 0 1 h-1 h h Figura 11.18 Descarte por izquierda. Se mantiene AVL. Caso a. 11.3.2. Continuar revisando factores de balance en el descarte. b) Al descartar por la izquierda, y en el proceso de revisión de los factores de balance, si se llega a un nodo con factor menos uno, se debe corregir el factor de ese nodo (quedando éste en cero) y es preciso seguir revisando en la vía de ascenso. Esto debido a que ese nodo cambió su altura de (h+1) a h. h+1 A A -1 0 h h h Figura 11.19 Descarte por izquierda. Se mantiene AVL. Caso b. 11.3.3. Rotación simple para corregir desbalance en descarte. Detener revisión. c) En la situación de la figura a la izquierda, se descarta por la izquierda. La figura central muestra la situación, y la necesidad de rebalancear por pérdida de propiedad AVL. Lo cual se logra con una rotación a la izquierda, que se muestra en la Figura 11.20 de la derecha, generando un árbol AVL. No es preciso seguir la revisión ascendente, ya que el subárbol, no cambia su altura. Profesor Leopoldo Silva Bijit 20-01-2010 14 Estructuras de Datos y Algoritmos A A 1 2 B cero B -1 A B 0 0 1 h-1 h h h h h h-1 h h Figura 11.20 Descarte por rama izquierda. Deja de ser AVL. Caso c. 11.3.4. Rotación doble para corregir el desbalance en descarte. d) En la situación de la figura 11.21 a la izquierda, se descarta por la izquierda. La figura central muestra la situación, y la necesidad de rebalancear por pérdida de propiedad AVL. Lo cual se logra con una doble rotación (primero a la derecha, luego a la izquierda). Es preciso seguir la revisión ascendente, ya que el subárbol, cambia su altura de (h+1) a h. A B 0 A 1 2 C negativo C -1 -1 B 0 h-1 h-1 ó C 0 0 B 0 h-1 h A h-1 h-2 h-1 h-1 h-1 ó h-1 h-1 h-1 ó h-2 h-2 Figura 11.21 Descarte por rama izquierda. Deja de ser AVL. Caso d. 11.3.5. Rotación simple para corregir desbalance en descarte. Continuar revisión. e) En la situación de la figura a la izquierda, se descarta por la izquierda. La figura central muestra la situación, y la necesidad de rebalancear por pérdida de propiedad AVL. Lo cual se logra con una rotación a la izquierda. Es preciso seguir la revisión ascendente, ya que el subárbol cambia su altura, de (h+1) antes del descarte a h. Profesor Leopoldo Silva Bijit 20-01-2010 h-1 Árboles balanceados AVL 15 A A 1 2 B positivo B B 1 1 h h-1 0 A 0 h-1 h h-1 h h-1 h h-1 Figura 11.22 Descarte por izquierda. Deja de ser AVL. Caso e. Las figuras centrales de 11.21 y 11.22 muestran que se puede discernir entre los casos d y e, observando el hijo derecho del nodo que pasó a tener factor de balance dos. Esto implica que la función descartar debe analizar 10 casos. Cinco en descartes por la izquierda y 5 por la derecha. Se analizan en detalle rotaciones simples, que se deben emplear para mantener la propiedad de árbol AVL, en aquellos casos que lo requieren. 11.4. Rotación simple a la izquierda. Al inicio t apunta a la raíz del subárbol. Luego de temp = t y t = t->right, queda la figura de la izquierda. Luego de temp->right = t->left; y t->left = temp queda la figura de la derecha. B A temp t 2 temp B a 0 A 1 b 0 c c a h h t b h+1 h h h+1 Figura 11.23 Rotación simple a la izquierda. En caso de un árbol AVL, la corrección de los factores de balance se puede efectuar según: temp->bal =0 y t->bal =0. Sin embargo para lograr una rutina general de rotación se analiza la siguiente situación: Profesor Leopoldo Silva Bijit 20-01-2010 16 Estructuras de Datos y Algoritmos B A temp temp nB t x t B A y nA a b c a b c Figura 11.24 Análisis de los factores de balance. Sean a, b y c los altos de los subárboles, que no cambian. Antes de la rotación, los factores de balance de los nodos A y B son x e y, respectivamente; luego de la rotación éstos se denominan: nA y nB, según se muestra en la Figura 11.24. En la figura de la izquierda se cumplen: y = c-b, x=b+1-a si b>c, o x=c+1-a si c>b En la figura de la derecha se cumplen, por la definición del factor de balance: nA= b-a, nB= c-1-a si a>b, o nB=c-1-b si b>a. Se desea determinar nA y nB en términos de x e y. Cálculo de nA: Reemplazando (b-a) por (x-1) para b>c, y por (c-a)-(c-b) para c>b, se obtienen: nA=x-1-0 con b>c o bien: nA=x-1-y para c>b Las últimas dos ecuaciones pueden anotarse: nA=x-1-max(y,0) Lo cual puede comprobarse, ya que si y es negativo (para b>c), queda nA=x-1; y si y es positivo (para c>b), queda nA=x-1-y. Cálculo de nB: Para a>b, se tiene reemplazando (c-a) por (b-a)+(c-b) si b>c se obtiene: nB=(c-a)-1=(x-1)+y-1 es decir: nB=x-2+y Para a>b, se tiene reemplazando (c-a) por (x-1) si c>b se obtiene nB=(c-a)-1=x-2+0. Las dos relaciones anteriores pueden anotarse, en forma compacta: Profesor Leopoldo Silva Bijit 20-01-2010 Árboles balanceados AVL 17 nB=x-2+min(y, 0) Lo cual puede comprobarse, ya que si y es negativo (para b>c) se tiene que min(y,0) es y; si y>0, se tiene que min(y,0) es cero. Para b>a, se tiene nB= y-1 Observando la siguiente relación, que puede deducirse de la Figura 11.24 derecha: nB = c-(max(a,b)+1) Entonces nB debe ser la menor de las diferencias posibles: nB = min(c-a-1, c-b-1) Reemplazando (c-a-1) por nB y (c-b-1) por (y-1), se tiene: nB = min(nB, y-1) Finalmente, reemplazando nB, en la expresión en la derecha por x-2+min(y, 0), calculada antes, se obtiene: nB = min(x-2+min(y,0), y-1) El siguiente segmento corrige factores de balance en una rotación simple a la izquierda: x = temp->bal; // oldbal(A) y = t->bal; // oldbal(B) temp->bal = x-1-max(y, 0); // newbal(A) t->bal = min(x-2+min(y, 0), y-1); // newbal(B) Los siguientes macros implementan las funciones mínimo y máximo # define max(A,B) ((A)>(B)?(A):(B)) /* Definición de macro */ # define min(A,B) ((A)>(B)?(B):(A)) Nótese los argumentos de los macros entre paréntesis. La rotación simple a la derecha es la imagen especular del caso recién analizado. 11.5 Operaciones. 11.5.1. Definición de tipos. typedef struct avlnode { int clave; int bal; /* Factor de balance -1,0,1 */ struct avlnode *left, *right; } nodo, *pnodo; Profesor Leopoldo Silva Bijit 20-01-2010 18 Estructuras de Datos y Algoritmos 11.5.2. Definición variables globales: Flag, key, alto_avl. int flag; /* Marca para registrar cambios de altura. En rebalance ascendente */ //flag = 1 indica que debe seguir el ascenso rebalanceando. int key; /* Variable global, para disminuir argumentos */ int alto_avl = 0; /* Altura árbol avl. Número de nodos desde la raíz a las hojas.*/ 11.5.3. Inserta nodo en sub-árbol apuntado por t. /* Mantiene variable global con el alto del árbol. */ pnodo InsertarAVL(int clave, pnodo t) { key = clave; //pasa argumento a global. t = insertR(t); if (flag == 1) alto_avl++; //si la propagación llega hasta la raíz, aumenta la altura. return t; } tree insertR(tree t) { if (t == NULL){ /* Llegó a un punto de inserción */ t = CreaNodo(key); /* Crea nuevo nodo */ t->bal = 0; /* Los dos hijos son nulos */ flag = 1; /* Marca necesidad de revisar balances */ return t; /* retorna puntero al insertado */ } else if (t->clave < key){ //desciende por la derecha t->right = insertR(t->right); //se pasa por la siguiente línea en la revisión ascendente t->bal += flag; /* Incrementa factor de balance */ } else if (t->clave > key){ //desciende por la izquierda t->left = insertR(t->left); //se corrige en el ascenso t->bal -= flag; /* Decrementa balance */ } else { /* (t->k == key) Ya estaba en el árbol */ Error(1); flag = 0; } if (flag == 0) /* No hay que rebalancear. Sigue el ascenso */ return t; Profesor Leopoldo Silva Bijit 20-01-2010 Árboles balanceados AVL 19 /*El código a continuación es el costo adicional para mantener propiedad AVL */ /* Mantiene árbol balanceado avl. Sólo una o dos rotaciones por inserción */ if(t->bal < -1) { /* Quedó desbalanceado por la izquierda. Espejos casos c y d.*/ if(t->left->bal > 0) /* Si hijo izquierdo está cargado a la derecha */ t->left = lrot(t->left); t = rrot(t); flag = 0; /* El subárbol no aumenta su altura */ } else if(t->bal > 1) { /* Si quedó desbalanceado por la derecha. Casos c y d.*/ if(t->right->bal < 0) /* Si hijo derecho está cargado a la izquierda Caso d. Fig. 11.16*/ t->right = rrot(t->right); t = lrot(t); /*caso c.*/ flag = 0; /* El subárbol no aumenta su altura */ } else if(t->bal == 0)/* La inserción lo balanceo */ flag = 0; /* El subárbol no aumenta su altura. Caso a. Fig. 11.8*/ else /* Quedó desbalanceado con -1 ó +1 Caso b. Fig. 11.9 */ flag = 1; /* Propaga ascendentemente la necesidad de rebalancear */ return t; } 11.5.4. Descarta nodo en sub-árbol apuntado por t. pnodo DescartarAVL(int clave, pnodo t) { key = clave; t = deleteR(t); if (flag == 1) alto_avl--; return t; } pnodo deleteR(pnodo t) { pnodo p; if(t == NULL) { /* No encontró nodo a descartar */ Error(0); flag = 0; } else if(t->clave < key) { //Comienza el descenso por la derecha t->right = deleteR(t->right); //aquí se llega en el retorno ascendente. t->bal -= flag; /* Se descartó por la derecha. Disminuye factor */ Profesor Leopoldo Silva Bijit 20-01-2010 20 Estructuras de Datos y Algoritmos //Se retorna después de la revisión de los factores } else if (t->clave > key) { //Desciende por la izquierda t->left = deleteR(t->left); //o se llega por esta vía si se descartó por la izquierda. t->bal += flag; /* se descartó por la izq. Aumenta factor de balance */ } else { /* (t->clave == key) */ /* Encontró el nodo a descartar */ if (t->left == NULL) { /*Si hay hijo derecho debe ser hoja, por ser AVL */ p = t; t = t->right; free(p); flag = 1; /* Debe seguir revisando factores de balance */ return t; /* ascendentemente */ } else if (t->right == NULL) { /*Si hay hijo izquierdo debe ser hoja */ p = t; t = t->left; free(p); flag = 1; /* Asciende revisando factores de balance */ return t; /* Corrigiendo */ } else { /* Tiene dos hijos */ if(t->bal<0) { /* Si cargado a la izquierda, elimina mayor descendiente hijo izq */ p = t->left; while (p->right != NULL) p = p->right; t->clave = p->clave; key = p->clave; //busca hoja a eliminar t->left = deleteR(t->left); t->bal += flag; /* incrementa factor de balance */ } else { /* Si cargado a la derecha, elimina menor descendiente hijo der */ p = t->right; while (p->left != NULL) p = p->left; t->clave = p->clave; key = p->clave; t->right = deleteR(t->right); t->bal -= flag; /* decrementa balance */ } } } /* Mantiene árbol balanceado avl. Sólo una o dos rotaciones por descarte */ if (flag == 0 ) /* No hay que rebalancear. Sigue el ascenso, sin rebalancear */ return t; Profesor Leopoldo Silva Bijit 20-01-2010 Árboles balanceados AVL 21 /* Hay que revisar factores de balance en el ascenso*/ if(t->bal < -1) { /* Si quedó desbalanceado por la izquierda y dejó de ser AVL */ if(t->left->bal > 0) { /*espejos casos c, d y e */ /* Si el hijo izquierdo está cargado a la derecha */ t->left = lrot(t->left); flag = 1; /*Continuar revisando factores */ } else if (t->left->bal == 0) flag = 0; /*No debe seguir el rebalance */ else flag = 1;/* Debe seguir revisando factores de balance */ t = rrot(t); } else if(t->bal > 1) { /* Si quedó desbalaceado por la derecha */ if(t->right->bal < 0) { /* Si hijo derecho está cargado a la izquierda */ t->right = rrot(t->right); flag = 1; //debe seguir revisando. Caso d. } else if (t->right->bal == 0) flag = 0; /* No debe seguir el rebalance. Caso c. */ else //positivo flag = 1;/* Debe seguir revisando factores de balance. Caso e. */ t = lrot(t); } else if (t->bal == 0) /* Si estaba en +1 ó -1 y queda en cero */ flag = 1; /* Debe seguir corrigiendo. Caso b.*/ else /* Si estaba en cero y queda en -1 ó +1 */ flag = 0; /* No debe seguir rebalanceando. Caso a.*/ return t; } 11.5.5. Rotaciones. /* Rotación Izquierda * * A B * / \ / \ * a B ==> A c * / \ / \ * b c a b * Sólo cambian los factores de balance de los nodos A y B * Los factores de balance de los sub-árboles no cambian. */ Profesor Leopoldo Silva Bijit 20-01-2010 22 Estructuras de Datos y Algoritmos static pnodo lrot(pnodo t) { pnodo temp; int x,y; temp = t; t = t->right; temp->right = t->left; t->left = temp; //Recalcula factores de balance de los dos nodos x = temp->bal; // oldbal(A) y = t->bal; // oldbal(B) temp->bal = x-1-max(y, 0); t->bal = min(x-2+min(y, 0), y-1); return t; } /* Rotación derecha * * A * / \ * B c * / \ * a b * */ static pnodo rrot(pnodo t) { tree temp = t; int x,y; ==> B / \ a A / \ b c t = t->left; temp->left = t->right; t->right = temp; x = temp->bal; y = t->bal; /* x=c-1-a ó x=c-1-b. y = b-a * nA = c-b. nB =c+1-a ó nB=b+1-a * nA= x+1-y o nA=x+1-0 * nA = x+1-min(y,0) * nB = max(b,c)+1-a => max(b-a+1,c-a+1) * => max(y+1,x+2+max(y,0)) */ temp->bal = x+1-min(y, 0); t->bal = max(x+2+max(y, 0), y+1); return t; } Profesor Leopoldo Silva Bijit 20-01-2010 Árboles balanceados AVL 23 11.5.6. Otras funciones. static void Error(int tipo) { if (tipo) printf("\nError en inserción\n"); else printf("\nError en descarte\n"); } int Altura(void) { return alto_avl; } pnodo deltree(pnodo t) //borra el árbol completo { alto_avl = 0; return deltreeR(t); } pnodo deltreeR(pnodo t) { if (t != NULL) { t->left = deltreeR(t->left); t->right = deltreeR(t->right); free(t); //borra la raíz subárbol } return NULL; } void inorder(pnodo t, int profundidad) { if (t != NULL) { inorder(t->left, profundidad+1); printf ("v= %d p=%d bal=%d \n", t->clave, profundidad, t->bal); inorder(t->right, profundidad+1); } } Profesor Leopoldo Silva Bijit 20-01-2010 24 Estructuras de Datos y Algoritmos Problemas resueltos. P11.1. Para el siguiente árbol AVL 7 3 8 4 1 Figura P11.1. a) Indique los factores de balance de cada nodo. b) Dibujar el árbol AVL, después de la inserción de un nodo con valor 2. ¿Qué operaciones se efectúan?. c) Habiendo ya insertado el nodo con valor 2, dibujar el árbol AVL, después de la inserción de un nodo con valor 6. ¿Qué operaciones se efectúan?. Solución. a) Los factores de balance: -1 0 3 8 0 0 1 7 0 4 Figura P11.2. b) Luego de insertar el 2, no queda AVL. Con una rotación simple a la derecha, se reestablece la propiedad AVL. +1 -2 0 7 3 -1 +1 1 -1 3 8 0 0 +1 1 +1 4 2 0 0 0 2 0 4 7 7 0 1 3 8 2 0 6 Figura P11.3. Profesor Leopoldo Silva Bijit 20-01-2010 0 8 +1 4 0 Árboles balanceados AVL 25 c) La inserción del 6, no requiere rotaciones para mantener la propiedad AVL. Ejercicios propuestos. E11.1 Dado el siguiente árbol AVL: 8 12 4 2 1 7 3 14 9 5 11 13 15 1 Figura E11.1. a) Determinar el árbol y el factor de balance de cada nodo después de Insertar nodos con valores 6 y 10. Especificar las operaciones elementales para mantener el balance, indicando cómo queda el árbol. b) Determinar el árbol y el factor de balance de cada nodo después de Descartar nodos con valores 13, 14, 15, 9 y 11. Especificar las operaciones elementales para mantener el balance, indicando cómo queda el árbol. Nota: en a) y b) se parte del árbol dado. Son situaciones independientes. Referencias. Niklaus Wirth, “Algorithms + Data Structures = Programs”, Prentice-Hall 1975. G.M. Adel'son-Vel'skii and E.M. Landis. “An algorithm for the organization of information.” Soviet Mathematics Monthly, Volume 3, pp.1259-1263, 1962. Profesor Leopoldo Silva Bijit 20-01-2010 26 Estructuras de Datos y Algoritmos Índice general. CAPÍTULO 11 ............................................................................................................................................1 ÁRBOLES BINARIOS BALANCEADOS DE BÚSQUEDA. AVL. ......................................................1 11.1 ANÁLISIS DE COMPLEJIDAD. ..............................................................................................................1 11.2. ANÁLISIS DE LA INSERCIÓN. .............................................................................................................6 11.2.1. Detención de revisión en ascenso. ...........................................................................................7 11.2.2. Continuar revisando factores de balance en ascenso. .............................................................7 11.2.3. Casos que producen desbalances. ............................................................................................8 11.2.3.1. Inserción externa por la derecha. ....................................................................................................... 8 11.2.3.2. Inserción interna por la derecha. ....................................................................................................... 9 11.3.4. Rotaciones para mantener propiedad AVL. .............................................................................9 11.3.4.1. Corrección con rotación simple en inserción................................................................................... 10 11.3.4.2. Corrección con rotación doble en inserción. ................................................................................... 11 11.3. ANÁLISIS DEL DESCARTE DE UN NODO. ..........................................................................................12 11.3.1. Detención de la revisión de los factores de balance en el descarte. ......................................12 11.3.2. Continuar revisando factores de balance en el descarte. ......................................................13 11.3.3. Rotación simple para corregir desbalance en descarte. Detener revisión.............................13 11.3.4. Rotación doble para corregir el desbalance en descarte. ......................................................14 11.3.5. Rotación simple para corregir desbalance en descarte. Continuar revisión. ........................14 11.4. ROTACIÓN SIMPLE A LA IZQUIERDA. ...............................................................................................15 11.5 OPERACIONES. ................................................................................................................................17 11.5.1. Definición de tipos. ................................................................................................................17 11.5.2. Definición variables globales: Flag, key, alto_avl. ..............................................................18 11.5.3. Inserta nodo en sub-árbol apuntado por t. ............................................................................18 11.5.4. Descarta nodo en sub-árbol apuntado por t. .........................................................................19 11.5.5. Rotaciones. .............................................................................................................................21 11.5.6. Otras funciones. .....................................................................................................................23 PROBLEMAS RESUELTOS. ........................................................................................................................24 P11.1. Para el siguiente árbol AVL ...................................................................................................24 EJERCICIOS PROPUESTOS. ........................................................................................................................25 E11.1 Dado el siguiente árbol AVL: ..................................................................................................25 REFERENCIAS. .........................................................................................................................................25 ÍNDICE GENERAL. ....................................................................................................................................26 ÍNDICE DE FIGURAS. ................................................................................................................................27 Profesor Leopoldo Silva Bijit 20-01-2010 Árboles balanceados AVL 27 Índice de figuras. Figura 11.1 Árboles Fibonacci AVL, con alturas 0, 1................................................................... 2 Figura 11.1.a. Árboles Fibonacci AVL, con altura 2. ................................................................... 2 Figura 11.2 Ejemplo árbol AVL Fibonacci, con altura 3. ............................................................. 2 Figura 11.3 Árbol AVL Fibonacci, con altura 4. .......................................................................... 3 Figura 11.4 Cota AVL en función de n. ........................................................................................ 4 Figura 11.5 Complejidad de la altura de un árbol AVL. ............................................................... 5 Figura 11.6 Alargue de altura árbol AVL, respecto de perfectamente balanceado ....................... 5 Figura 11.6.a. Razón áurea . ........................................................................................................ 6 Figura 11.7 Inserciones que sólo requieren recalcular factor de balance. ..................................... 7 Figura 11.8 Detención de revisión en ascenso. Caso a.................................................................. 7 Figura 11.9 Continuar revisión en ascenso. Caso b....................................................................... 8 Figura 11.10 Árbol AVL, para analizar pérdida de propiedad AVL. ............................................ 8 Figura 11.11 Árbol no AVL, después de inserción externa por la derecha. .................................. 9 Figura 11.12 Árbol no AVL, después de inserción interna por la derecha. .................................. 9 Figura 11.13 Árbol AVL de Figura 11.11, después de rotación simple a la izquierda. .............. 10 Figura 11.14 Árbol AVL de la figura 11.12, después de doble rotación..................................... 10 Figura 11.15 Generalización de caso c). Rotación simple. ......................................................... 11 Figura 11.16 Generalización de caso d). ..................................................................................... 11 Figura 11.17 Generalización de caso d). Doble rotación. ........................................................... 12 Figura 11.18 Descarte por izquierda. Se mantiene AVL. Caso a. ............................................... 13 Figura 11.19 Descarte por izquierda. Se mantiene AVL. Caso b................................................ 13 Figura 11.20 Descarte por rama izquierda. Deja de ser AVL. Caso c......................................... 14 Figura 11.21 Descarte por rama izquierda. Deja de ser AVL. Caso d. ....................................... 14 Figura 11.22 Descarte por izquierda. Deja de ser AVL. Caso e.................................................. 15 Figura 11.23 Rotación simple a la izquierda. .............................................................................. 15 Figura 11.24 Análisis de los factores de balance. ....................................................................... 16 Figura P11.1. ............................................................................................................................... 24 Figura P11.2. ............................................................................................................................... 24 Figura P11.3. ............................................................................................................................... 24 Figura E11.1. ............................................................................................................................... 25 Profesor Leopoldo Silva Bijit 20-01-2010