-- AUTOR: Elvira Mayordomo Cámara
-- PROYECTO: módulo de implementación del
-- TAD arboles AVL (árboles binarios de búsqueda
-- casi equilibrados)
-- FICHERO: avl.adb
-- FECHA: 14-11-03
with unchecked_deallocation;
with text_io;
use text_io;
package body avl is
procedure disponer is new unchecked_deallocation(nodo,arbin);
procedure reequilibrar(a:in arbin);
-- Pre: partiendo de un árbol AVL,
-- uno de los hijos de la raiz a ha cambiado en altura
-- (sumando ó restando 1)
-- por lo que las alturas de a hacia arriba
-- deben ser recalculadas y posiblemente el árbol
-- reequilibrado.
-- Post: a tiene los mismos nodos y es
-- un AVL
-- coste en tiempo: para un árbol de n nodos tarda
-- O(log n)
procedure creaVacio(a:out arbin) is
-- Post: a=aVacío
-- coste en tiempo O(1)
begin
a:=null;
end creaVacio;
procedure insertarrec(a,nuevodato:in out arbin) is
-- Pre: a=a0
-- Post: a=insertar(a0,e) pero sin reequilibrado
-- resultado devuelve el punto de inserción del
-- nuevo nodo.
-- coste en tiempo: para un árbol de n nodos tarda
-- O(log n)
begin
if a=null then
a:=nuevodato;
elsif (nuevodato.dato<=a.dato) then
nuevodato.padre:=a;
insertarrec(a.izq,nuevodato);
else
nuevodato.padre:=a;
insertarrec(a.der,nuevodato);
end if;
end insertarrec;
procedure insertar(a:in out arbin; e:in elemento) is
-- Pre: a=a0
-- Post: a=insertar(a0,e)
-- coste en tiempo: para un árbol de n nodos tarda
-- O(log n)
nuevodato: arbin;
begin
nuevodato:=new nodo'(e,null,null,null,0);
insertarrec(a,nuevodato);
reequilibrar(nuevodato.padre);
end insertar;
function esta(a:arbin; e:elemento) return
boolean is
-- Post: esta(a,e)= está?(a,e)
-- coste en tiempo: para un árbol de n nodos tarda
-- O(log n)
resultado: boolean;
begin
resultado:=false;
if a/=null then
if (a.dato = e) then resultado:=true;
elsif (e<=a.dato) then
resultado:=esta(a.izq,e);
else resultado:=esta(a.der,e);
end if;
end if;
return resultado;
end esta;
function min(a:arbin) return elemento is
-- Pre: not(esvacío(a))
-- Post: min(a)= min(a)
-- coste en tiempo: para un árbol de n nodos tarda
-- O(log n)
begin
if a.izq=null then return a.dato;
else return min(a.izq);
end if;
end min;
function max(a:arbin) return elemento is
-- Pre: not(esvacío(a))
-- Post: max(a)= max(a)
-- coste en tiempo: para un árbol de n nodos tarda
-- O(log n)
begin
if a.der=null then return a.dato;
else return max(a.der);
end if;
end max;
procedure borrarrec(a:in out arbin; e:in
elemento; lugar:out arbin) is
-- Pre: a=a0
-- Post: a=borrar(a0,e) sin reequilibrar
-- lugar tiene al padre del borrado
-- coste en tiempo: para un árbol de n nodos tarda
-- O(log n)
aux:arbin;
nuevaraiz:elemento;
begin
if a/=null then
if (a.dato = e) then
if a.der=null and a.izq=null then
aux:=a;
lugar:=a.padre;
a:=null;
disponer(aux);
elsif a.izq/=null then
nuevaraiz:=max(a.izq);
a.dato:=nuevaraiz;
borrarrec(a.izq,nuevaraiz,lugar);
else
nuevaraiz:=min(a.der);
a.dato:=nuevaraiz;
borrarrec(a.der,nuevaraiz,lugar);
end if;
elsif (e<=a.dato) then
borrarrec(a.izq,e,lugar);
else borrarrec(a.der,e,lugar);
end if;
end if;
end borrarrec;
procedure borrar(a:in out arbin; e:in
elemento) is
-- Pre: a=a0
-- Post: a=borrar(a0,e)
-- coste en tiempo: para un árbol de n nodos tarda
-- O(log n)
lugar:arbin;
begin
borrarrec(a,e,lugar);
if lugar/=null then
reequilibrar(lugar);
end if;
end borrar;
function altura(a:arbin) return integer is
-- calcula la altura de a a partir de las de
-- a.izq y a.der
-- coste en tiempo O(1)
altizq,altder: integer;
begin
if a=null then
return -1;
else
if a.der/=null then
altder:=a.der.altura;
else
altder:=-1;
end if;
if a.izq/=null then
altizq:=a.izq.altura;
else
altizq:=-1;
end if;
return(1+integer'Max(altizq,altder));
end if;
end altura;
function factorequilibrio(a:arbin) return integer is
-- calcula el factor de equilibrio de a
-- coste en tiempo O(1)
begin
if a=null then
return 0;
else
return altura(a.der)-altura(a.izq);
end if;
end factorequilibrio;
procedure rotacionSder(a:in out arbin) is
-- Pre: a/=null y a.izq/=null
-- Post: realiza una rotación simple a dcha
-- sobre a
-- coste en tiempo O(1)
NA, NB: nodo;
begin
NA:=a.all;
NB:=a.izq.all;
a.dato:=NB.dato;
a.der:=a.izq;
a.der.padre:=a;
a.izq:=NB.izq;
if a.izq/=null then a.izq.padre:=a; end if;
a.der.dato:=NA.dato;
a.der.izq:=NB.der;
if a.der.izq/=null then
a.der.izq.padre:=a.der;
end if;
a.der.der:=NA.der;
if a.der.der/=null then
a.der.der.padre:=a.der;
end if;
a.der.altura:=altura(a.der);
a.altura:=altura(a);
end rotacionSder;
procedure rotacionSizq(a:in out arbin) is
-- Pre: a/=null y a.der/=null
-- Post: realiza una rotación simple a izda
-- sobre a
-- coste en tiempo O(1)
NA, NB: nodo;
begin
NA:=a.all;
NB:=a.der.all;
a.dato:=NB.dato;
a.izq:=a.der;
a.izq.padre:=a;
a.der:=NB.der;
if a.der/=null then a.der.padre:=a; end if;
a.izq.dato:=NA.dato;
a.izq.der:=NB.izq;
if a.izq.der/=null then
a.izq.der.padre:=a.izq;
end if;
a.izq.izq:=NA.izq;
if a.izq.izq/=null then
a.izq.izq.padre:=a.izq;
end if;
a.izq.altura:=altura(a.izq);
a.altura:=altura(a);
end rotacionSizq;
procedure rotacionDder(a:in out arbin) is
-- Pre: a/=null, a.izq/=null y a.izq.der/=null
-- Post: realiza una rotación doble a dcha
-- sobre a
-- coste en tiempo O(1)
NA, NB, NC: nodo;
begin
NA:=a.all;
NC:=a.der.all;
NB:=NC.izq.all;
a.dato:=NB.dato;
a.izq:=NC.izq;
a.izq.padre:=a;
a.izq.dato:=NA.dato;
a.izq.izq:=NA.izq;
if a.izq.izq/=null then
a.izq.izq.padre:=a.izq;
end if;
a.izq.der:=NB.izq;
if a.izq.der/=null then
a.izq.der.padre:=a.izq;
end if;
a.der.izq:=NB.der;
if a.der.izq/=null then
a.der.izq.padre:=a.der;
end if;
a.izq.altura:=altura(a.izq);
a.der.altura:=altura(a.der);
a.altura:=altura(a);
end rotacionDder;
procedure rotacionDizq(a:in out arbin) is
-- Pre: a/=null, a.der/=null y a.der.izq/=null
-- Post: realiza una rotación doble a izda
-- sobre a
-- coste en tiempo O(1)
NA, NB, NC: nodo;
begin
NC:=a.all;
NA:=a.izq.all;
NB:=NA.der.all;
a.dato:=NB.dato;
a.der:=NA.der;
a.der.padre:=a;
a.der.dato:=NC.dato;
a.der.izq:=NB.der;
if a.der.izq/=null then
a.der.izq.padre:=a.der;
end if;
a.der.der:=NC.der;
if a.der.der/=null then
a.der.der.padre:=a.der;
end if;
a.izq.der:=NB.izq;
if a.izq.der/=null then
a.izq.der.padre:=a.izq;
end if;
a.izq.altura:=altura(a.izq);
a.der.altura:=altura(a.der);
a.altura:=altura(a);
end rotacionDizq;
procedure rotar(a:in out arbin) is
-- Pre: a=a0 es un árbol en el que la raiz tiene factor de
-- equilibrio +2 ó -2 y el resto de los nodos entre -1 y +1.
-- Post: a es un árbol AVL con los mismos
-- valores que a0 y altura(a)=altura(a0)-1
-- coste en tiempo O(1)
begin
if factorequilibrio (a)=-2 then
if factorequilibrio (a.izq)= 1 then
rotacionDizq(a);
else
rotacionSder(a);
end if;
else
if factorequilibrio (a.der)= -1 then
rotacionDder(a);
else
rotacionSizq(a);
end if;
end if;
end rotar;
procedure reequilibrar(a:in arbin) is
-- uno de los hijos de a ha cambiado en altura
-- por lo que las alturas de a hacia arriba
-- deben ser recalculadas y posiblemente el árbol
-- reequilibrado.
-- coste en tiempo: para un árbol de n nodos tarda
-- O(log n)
aux: arbin;
fe: integer;
desequilibrado:boolean;
begin
-- actualización de alturas
aux:=a;
desequilibrado:=false;
while aux/=null and not desequilibrado loop
aux.altura:=altura(aux);
fe:=factorequilibrio(aux);
desequilibrado:=(fe=2) or(fe=-2);
if not desequilibrado then aux:=aux.padre; end if;
end loop;
if desequilibrado then rotar(aux); end if;
end reequilibrar;
procedure preOrden(a:in arbin) is
-- muestra por pantalla el preorden de a
begin
if a/=null then
put(a.dato);
preOrden(a.izq);
preOrden(a.der);
end if;
end preOrden;
procedure postOrden(a:in arbin) is
-- muestra por pantalla el preorden de a
begin
if a/=null then
postOrden(a.izq);
postOrden(a.der);
put(a.dato);
end if;
end postOrden;
procedure mostrar(a:in arbin) is
-- Muestra por pantalla preorden y postorden
begin
put_line("El preorden es:");
preOrden(a);
put_line("");
put_line("El postorden es:");
postOrden(a);
put_line("");
end mostrar;
end avl;
syntax highlighted by Code2HTML, v. 0.9.1