Está en la página 1de 91

rboles

Fundamentos de Anlisis y Diseo de Algoritmos

Universidad del Valle


Facultad de Ingeniera
Escuela de Ingeniera de Sistemas y Computacin

Curso: Fundamento de Anlisis y Diseo de


Algoritmos(FADA)
Cdigo: 750094M

Estudiante: Dary Nadyme Cardona Z.


Cdigo: 0452383
Profesor: Ing. Celimo Orozco Marin

YUMBO, DICIEMBRE DE 2007

Pgina 1 de 91

ESTRUCTURA DE RBOLES

Definicin y conceptos bsicos


- Un rbol es una estructura de datos no lineal y homognea en el que cada
elemento puede tener varios elementos posteriores, pero tan slo puede
tener un elemento anterior.
- Es una estructura jerrquica aplicada sobre una coleccin de elementos u
objetos llamados nodos; de los cuales uno es conocido como raz. Adems se
crea una relacin o parentesco entre los nodos dando lugar a trminos como
padre, hijo, hermano, antecesor, sucesor, ancestro, etc.
- Un rbol es una estructura compuesta por un dato y varios rboles. Dado
un nodo cualquiera de la estructura, podemos considerarlo como una
estructura independiente. Es decir, un nodo cualquiera puede ser considerado
como la raz de un rbol completo.
- Son estructuras dinmicas no lineales. Dinmicas porque las estructuras de
rbol pueden cambiar durante la ejecucin de un programa. No lineales,
puesto que a cada elemento del rbol pueden seguirle varios elementos. En
las estructuras de datos lineales cada elemento tiene un nico elemento
anterior y un nico elemento posterior.
Creo que la mayora, sino es que todos, hemos utilizado los rboles cuando
hemos hecho un rbol genealgico o alguna estructura jerrquica de alguna
organizacin. Y que me dicen de la forma en la que organizamos la
informacin en nuestras maquinas (se hace en una estructura de directorios y
subdirectorios en forma de rbol, para facilitar su bsqueda).
Talvez sin darnos cuenta, pero hemos manejado el concepto de rbol.

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

Nodo padre: Nodo que contiene un puntero al nodo actual. En un


rbol un nodo solo puede tener un nodo padre. X es padre de Y s y
solo s el nodo X apunta a Y. Tambin se dice que X es antecesor de Y.
En la Figura 1: B es padre de E y F.
Nodo hijo: Cualquiera de los nodos apuntados por uno de los nodos
del rbol. Un nodo puede tener varios hijos. X es hijo de Y, s y solo s
el nodo X es apuntado por Y. Tambin se dice que X es descendiente
directo de Y. En la Figura 1: E es hijo de B.
Hermano: Dos nodos sern hermanos si son descendientes directos
de un mismo nodo. En la Figura 1: E y F son hermanos
Orden: Es el nmero potencial de hijos que puede tener cada
elemento de rbol. De este modo, diremos que un rbol en el que
cada nodo puede apuntar a otros dos es de orden dos, si puede
apuntar a tres ser de orden tres, etc.
Altura: La altura de un rbol se define como el nivel del nodo de
mayor nivel. Como cada nodo de un rbol puede considerarse a su vez
como la raz de un rbol.
Peso: Es el nmero de nodos del rbol sin contar la raz. El rbol de la
Figura 1 tiene altura 3, la rama B tiene altura 2, la rama G tiene altura
1, la N cero...
Camino: Es una secuencia de nodos, en el que dos nodos
consecutivos cualesquiera son padre e hijo. En el ejemplo A-D-H y AC-G-M son caminos.
Longitud de camino: Es el nmero de arcos que deben ser
recorridos para llegar desde la raz al nodo X. Por definicin la raz
tiene longitud de camino 1, y sus descendientes directos longitud de
camino 2 y as sucesivamente
Raz: es aquel elemento que no tiene antecesor. En la Figura 1 A es el
nodo raz.
Rama: arista entre dos nodos. En el ejemplo A-B-E-K y A-B-F son
ramas.
Antecesor: un nodo X es antecesor de un nodo Y si por alguna de las
ramas de X se puede llegar a Y.
Sucesor: un nodo X es sucesor de un nodo Y si por alguna de las
ramas de Y se puede llegar a X.
Grado de un nodo: el nmero de descendientes directos que tiene.
Hoja: nodo que no tiene descendientes: grado 0.
Nodo interno: aquel que tiene al menos un descendiente.
Nivel: nmero de ramas que hay que recorrer para llegar de la raz a
un nodo.
Anchura: es el mayor valor del nmero de nodos que hay en un nivel.

Pgina 3 de 91

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

rboles binarios
Tipos de rboles binarios
Un rbol binario es una estructura de datos de tipo rbol en donde cada uno
de los nodos del rbol puede tener 0, 1, 2 subrboles llamados de acuerdo
a su caso como:
Si el nodo raz tiene 0 relaciones se llama hoja.
Si el nodo raz tiene 1 relacin a la izquierda, el segundo elemento de
la relacin es el subrbol izquierdo.
Si el nodo raz tiene 1 relacin a la derecha, el segundo elemento de la
relacin es el subrbol derecho.
Existen dos tipos de rboles binarios que se consideran especiales en funcin
de ciertas propiedades.
Estos son los siguientes:
1. rbol binario equilibrado
2. rbol binario completo
1. rbol binario equilibrado
Es un rbol en el que en todos sus nodos se cumple la siguiente propiedad:

|Altura (subrbol _ izquierdo) altura (subrbol _ derecho) | 1

2. rbol binario completo


Es un rbol en el que todos los nodos tienen dos hijos y todas las hojas estn
en el mismo nivel. Se denomina completo porque cada nodo, excepto las
hojas, tiene el mximo de hijos que puede tener.

Pgina 5 de 91

Recorridos por rboles


Una de las cosas que debemos poder hacer con un rbol es poder movernos
a travs de la informacin que este contiene. El modo evidente de moverse a
travs de las ramas de un rbol es siguiendo las referencias de los nodos que
las componen. Los recorridos dependen en gran medida del tipo y propsito
del rbol, pero hay ciertos recorridos que usaremos frecuentemente. Se trata
de aquellos recorridos que incluyen todo el rbol.
Hay tres formas de recorrer un rbol completo, y las tres se suelen
implementar mediante recursividad.
En los tres casos se sigue siempre a partir de cada nodo todas las ramas una
por una.
Estos tres casos son:
Pre-orden
In-orden
Post-orden

Recorrido Pre-orden (N I D)
En este recorrido lo primero que se obtiene o evala es el nodo, antes de
recorrer las ramas; posteriormente se recorre la rama izquierda y finalmente
la rama derecha. El orden es Nodo Izquierda Derecha (N I D).
El recorrido Pre-orden de nuestro rbol de la Figura 3 es: M E A R O
NQV
Y el recorrido Pre-orden del rbol de la Figura 5 es: N E A G R O V

Recorrido In-orden (I N D)
En este recorrido se procesa la primera rama (rama izquierda), despus el
nodo y finalmente la ultima rama (rama derecha). El orden es: Izquierda
Nodo Derecha (I N D).
El recorrido In-orden de nuestro rbol de la Figura 3 es: A E M N O
QRV
Y el recorrido In-orden del rbol de la Figura 5 es: A E G N O R V
Recorrido Post-orden (I D R)
En este recorrido se primero se procesan las ramas para finalmente procesar
el nodo. El orden de este recorrido es: Izquierda Derecha Nodo (I D
N).
El recorrido Post-orden del rbol de la Figura 3 es: A E N Q O V R
M
Y el recorrido Post-orden del rbol de la Figura 5 es: A G E O V R
N

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

Implementaciones del rbol binario


Para poder implementar un rbol binario primero debemos definir la
estructura de los nodos. Cada nodo del rbol estar formado por tres partes:
La informacin contenida en el nodo, la cual puede ser un tipo
primitivo o puede ser cualquier tipo de objeto.
Un enlace al hijo derecho (raz del subrbol derecho).
Un enlace al hijo izquierdo (raz del subrbol izquierdo).

Grficamente.

Frecuentemente, aunque tampoco es estrictamente necesario, para hacer


ms fcil moverse a travs del rbol, aadiremos un puntero a cada nodo
que apunte al nodo padre. De este modo podremos avanzar en direccin a la
raz, y no slo hacia las hojas. Si implementamos este puntero nuestro nodo
estara compuesto por cuatro partes:
Un enlace al padre del nodo
La informacin contenida en el nodo, la cual puede ser un tipo
primitivo o puede ser cualquier tipo de objeto
Un enlace al hijo derecho (raz del subrbol derecho)
Un enlace al hijo izquierdo (raz del subrbol izquierdo)

Pgina 7 de 91

Implementacin en C++
//Este programa permite generar nmeros aleatorios y los
inserta en un rbol binario adems de obtener los niveles
mximos y mnimo saca la diferencia de estos mismos y me
dice cuantas veces.
#include<stdlib.h>
#include<stdio.h>
#include<conio.h>
#include<iostream.h>
#include<dos.h>
#define VERDADERO 1
#define FALSO 0
#define VECES 50
efecta la operacin
#define cant_num 100
tendr el rbol
#define RANGO 1000

//la cantidad de veces que se


//la cantidad de nmeros que
//el rango de nmeros aleatorios

typedef struct tipoceldaABB


{
struct tipoceldaABB *izq,*der;
int etiqueta;
} *nodoABB;
typedef nodoABB ABB;
ABB Crear(int et)
{
ABB raiz;
raiz = new(tipoceldaABB);
if (raiz == NULL)
printf("Memoria Insuficiente.");
raiz->izq =NULL;
raiz->der = NULL;
raiz->etiqueta = et;
return(raiz);
}
void Inserta(int x,ABB *t)
{
if(!(*t)){
*t=(nodoABB)malloc(sizeof(struct tipoceldaABB));
if(!(*t)){
printf("Memoria Insuficiente.");
}
(*t)->etiqueta=x;
(*t)->izq=NULL;
(*t)->der=NULL;
} else if(x<(*t)->etiqueta)

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

Inserta(x,&((*t)->izq));
else
Inserta(x,&((*t)->der));
}
int nivel_mayor(ABB p)
{
if(p==NULL) return 0;
else
{
int nivelI=nivel_mayor(p->izq);
int nivelD=nivel_mayor(p->der);
if (nivelI>nivelD) return nivelI+1;
else
return nivelD+1;
}
}
int nivel_menor(ABB p)
{
if(p==NULL) return 0;
else
{
int nivelI=nivel_menor(p->izq);
int nivelD=nivel_menor(p->der);
if (nivelI<nivelD) return nivelI+1;
else
return nivelD+1;
}
}
void main()
{
int res;
int arr[VECES];
int num;
int alto[50];
int bajo[50];
ABB raiz;
randomize();
for(int CONT1=1;CONT1<=VECES;CONT1++)
{
clrscr();
cout<<" LOS NUMEROS INSERTADOS EN EL ARBOL
SON..."<<endl;
for(int CONT2=1;CONT2<=cant_num;CONT2++)
{
num=random(RANGO);
//genero el numero aleatorio
cout<<num<<"\t";
if(CONT2>1) Inserta(num,&raiz);
else
raiz=Crear(num);
}
alto[CONT1]=nivel_mayor(raiz);

Pgina 9 de 91

printf("EL NIVEL MAS ALTO DEL %d ARBOL GENERADO ES =


%d\n",CONT1,alto[CONT1]);
bajo[CONT1]=nivel_menor(raiz);
printf("EL NIVEL MAS BAJO DEL %d ARBOL GENERADO ES =
%d",CONT1,bajo[CONT1]);
arr[CONT1]=alto[CONT1]-bajo[CONT1];
getch();
}
clrscr();
for(int x=1;x<=RANGO;x++)
{
res=0;
for(int i=1;i<=cant_num;i++)
{
if(x==arr[i])
res++;
}
if(res>0) printf("SE REPITEN %d VECES EL NUMERO
%d\n",res,x);
}
getch();
}

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

/* Arboles Binarios Perfectamente Equilibrados.


Programa compilado con Turbo C version 2.01.*/
#include
#include
#include
#include

<stdio.h>
<conio.h>
<alloc.h>
<process.h>

struct Arbol{
int Dato;
struct Arbol *Izq;
struct Arbol *Der;
};
struct Arbol *ConstruirArbol(int);
void ImprimeArbol(struct Arbol *,int);
void Error();
int main(void)
{
int nodos;
struct Arbol *Raiz;
system("cls");
printf("Numero de nodos: ");
scanf("%d",&nodos);
printf("\nIntroduce los datos.\n\n");
Raiz=ConstruirArbol(nodos);
printf("\nImpresion del Arbol.\n\n");
ImprimeArbol(Raiz,0);
getch();
return 0;
}
void Error(void)
{
perror("error: No hay memoria.\n");
getch();
abort();
}
struct Arbol *NuevoNodo(void)
{
struct Arbol *Raiz=(struct Arbol
*)malloc(sizeof(struct Arbol));
if(!Raiz) Error();
return Raiz;
}
struct Arbol *ConstruirArbol(int nodos)
{
struct Arbol *Raiz;
int Ni,Nd;
if(nodos==0)
return NULL;

Pgina 11 de 91

else{
Ni=nodos/2;
Nd=nodos-Ni-1;
Raiz=NuevoNodo();
printf("Dato-> ");
scanf("%d",&Raiz->Dato);
Raiz->Izq=ConstruirArbol(Ni);
Raiz->Der=ConstruirArbol(Nd);
return Raiz;
}
}
void ImprimeArbol(struct Arbol *Raiz,int n)
{
int i;
if(Raiz==NULL) return;
ImprimeArbol(Raiz->Izq,n+1);
for(i=0;i<n;i++)
printf(" ");
printf("%d\n",Raiz->Dato);
ImprimeArbol(Raiz->Der,n+1);
}

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

Implementacin en Java
//Programa que permite crear un arbol binario y hacer sus respectivos
recorridos
Clase Nodo binario
static int size (NodoB a){...;}
static int height (NodoB a){...;}
void preorder (NodoB a){...;}
void inorder (NodoB a){...;}
void postorder (NodoB a){...;}
//Clase rbol binario...
class ArbolB {
protected NodoB raiz;
ArbolB() {raiz=null;}
ArbolB(Object o){raiz=new NodoB(o);}
public int size()
{return NodoB.size(raiz);}
public int height()
{return NodoB.height(raiz);}
public void preorder ()
{if (raiz!=null) raiz.preorder();}
public void inorder ()
{if (raiz!=null) raiz.inorder();}
public void postorder ()
{if (raiz!=null) raiz.postorder();}
}
// Tamao
static int size (NodoB a){
if (a==null)
return 0;
else
return 1+size(a.izq)+size(a.der);
}
// Altura
static int height (NodoB a){
if (a==null)
return (-1);
else
return 1+Math.max(height(a.izq),
height(a.der));
}
//RECORRIDOS

Pgina 13 de 91

// preorden
void preorder (){
System.out.println(d);
if (izq != null)
izq.preorder();
if (der != null)
der.preorder();
}
//postorden
void postorder (){
if (izq != null)
izq.postorder();
if (der != null)
der.postorder();
System.out.println(d);
}
// inorden
void inorder (){
if (izq != null)
izq.inorder();
System.out.println(d);
if (der != null)
der.inorder();
}

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

rboles binarios de bsqueda (ABB)


Se trata de rboles de orden 2 en los que se cumple que para cada nodo, el
valor de la clave de la raz del subrbol izquierdo es menor que el valor de la
clave del nodo y que el valor de la clave raz del subrbol derecho es mayor
que el valor de la clave del nodo.
La bsqueda en rboles binarios es un mtodo de bsqueda simple, dinmico
y eficiente considerado como uno de los fundamentales en Ciencia de la
Computacin. De toda la terminologa sobre rboles, tan slo recordar que la
propiedad que define un rbol binario es que cada nodo tiene a lo ms un
hijo a la izquierda y uno a la derecha. Para construir los algoritmos
consideraremos que cada nodo contiene un registro con un valor clave a
travs del cual efectuaremos las bsquedas. En las implementaciones que
presentaremos slo se considerar en cada nodo del rbol un valor del tipo
tElemento aunque en un caso general ese tipo estar compuesto por dos:
una clave indicando el campo por el cual se realiza la ordenacin y una
informacin asociada a dicha clave o visto de otra forma, una informacin
que puede ser compuesta en la cual existe definido un orden.
Elementos: Los elementos de un rbol binario de bsqueda son nodos. Se
asume que cada nodo contiene un elemento estndar y es identificado de
manera nica por el campo clave del elemento.
Estructura: La estructura del rbol binario de bsqueda es la misma del
rbol binario excepto que en el rbol de bsqueda, si N es algn nodo del
rbol todos los nodos en su subrbol izquierdo tienen campos de clasificacin
menores que los de N y todos los nodos en su subrbol derecho tienen
campos de clasificacin mayores que los de N.
Un rbol binario de bsqueda(ABB) es un rbol binario con la propiedad de
que todos los elementos almacenados en el subrbol izquierdo de cualquier
nodo x son menores que el elemento almacenado en x ,y todos los elementos
almacenados en el subrbol derecho de x son mayores que el elemento
almacenado en x.

Pgina 15 de 91

La figura 1 muestra dos ABB construidos en base al mismo conjunto de


enteros:

Figura 1: Dos ABB con los mismos elementos

Operaciones en ABB
El repertorio de operaciones que se pueden realizar sobre un ABB es parecido
al que realizbamos sobre otras estructuras de datos, ms alguna otra propia
de rboles:
Buscar un elemento.
Insertar un elemento.
Borrar un elemento.
Movimientos a travs del rbol:
o Izquierda.
o Derecha.
o Raz.
Informacin:
o Comprobar si un rbol est vaco.
o Calcular el nmero de nodos.
o Comprobar si el nodo es hoja.
o Calcular la altura de un nodo.
o Calcular la altura de un rbol.

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

Buscar un elemento.
Partiendo siempre del nodo raz, el modo de buscar un elemento se define de
forma recursiva.
Si el rbol est vaco, terminamos la bsqueda: el elemento no est en
el rbol.
Si el valor del nodo raz es igual que el del elemento que buscamos,
terminamos la bsqueda con xito.
Si el valor del nodo raz es mayor que el elemento que buscamos,
continuaremos la bsqueda en el rbol izquierdo.
Si el valor del nodo raz es menor que el elemento que buscamos,
continuaremos la bsqueda en el rbol derecho.
El valor de retorno de una funcin de bsqueda en un ABB puede ser un
puntero al nodo encontrado, o NULL, si no se ha encontrado.

Insertar un elemento
Para insertar un elemento nos basamos en el algoritmo de bsqueda. Si el
elemento est en el rbol no lo insertaremos. Si no lo est, lo insertaremos a
continuacin del ltimo nodo visitado.
Necesitamos un puntero auxiliar para conservar una referencia al padre del
nodo raz actual. El valor inicial para ese puntero es NULL.
Padre = NULL
nodo = Raiz
Bucle: mientras actual no sea un rbol vaco o hasta que se
encuentre el elemento.
o Si el valor del nodo raz es mayor que el elemento que
buscamos, continuaremos la bsqueda en el rbol
izquierdo: Padre=nodo, nodo=nodo->izquierdo.
o Si el valor del nodo raz es menor que el elemento que
buscamos, continuaremos la bsqueda en el rbol derecho:
Padre=nodo, nodo=nodo->derecho.
Si nodo no es NULL, el elemento est en el rbol, por lo tanto
salimos.
Si Padre es NULL, el rbol estaba vaco, por lo tanto, el nuevo
rbol slo contendr el nuevo elemento, que ser la raz del rbol.
Si el elemento es menor que el Padre, entonces insertamos el
nuevo elemento como un nuevo rbol izquierdo de Padre.
Si el elemento es mayor que el Padre, entonces insertamos el
nuevo elemento como un nuevo rbol derecho de Padre.
Este modo de actuar asegura que el rbol sigue siendo ABB.

Pgina 17 de 91

Borrar un elemento
Para borrar un elemento tambin nos basamos en el algoritmo de bsqueda.
Si el elemento no est en el rbol no lo podremos borrar. Si est, hay dos
casos posibles:
1. Se trata de un nodo hoja: en ese caso lo borraremos directamente.
2. Se trata de un nodo rama: en ese caso no podemos eliminarlo, puesto
que perderamos todos los elementos del rbol de que el nodo actual
es padre. En su lugar buscamos el nodo ms a la izquierda del
subrbol derecho, o el ms a la derecha del subrbol izquierdo e
intercambiamos sus valores. A continuacin eliminamos el nodo hoja.
Necesitamos un puntero auxiliar para conservar una referencia al padre del
nodo raz actual. El valor inicial para ese puntero es NULL.
Si se espera que el nmero de eliminaciones sea pequeo, la
eliminacin perezosa es una buena estrategia. Al eliminar un
elemento, se deja en el rbol marcndolo como eliminado. Habiendo
claves duplicadas, es posible decrementar el campo con la
frecuencia de apariciones. Si una clave eliminada se vuelve a
insertar, se evita la sobrecarga de asignar un nodo nuevo.
Si el nmero de nodos reales en el rbol es igual al nmero de
nodos eliminados, se espera que la profundidad del rbol solo
aumente en uno (por qu?).
o La penalizacin de tiempo es pequea.

Recorridos de un rbol
Las versiones recursivas de los recorridos son costosas debido a la gran
cantidad de llamadas recursivas que pueden llegar a copar la pila (stack)
Se prefieren entonces versiones no recursivas para dichos recorridos
Las versiones no recursivas de estos recorridos requieren el uso de
un arreglo (o lista) auxiliar de apuntadores a los nodos.
Su codificacin es menos clara que sus versiones recursivas
En orden: Se procesa el subrbol izquierdo, el nodo actual y, por ultimo, el
subrbol derecho. O(n)
Post-orden: Ambos subrboles primero. O(n)
Pre-orden: El nodo se procesa antes. Ej.: una funcin que marcase cada
nodo con su profundidad. O(n)
Orden de nivel: Todos los nodos con profundidad p se procesan antes que
cualquier nodo con profundidad p+1.
Se usa una cola en vez de la pila implcita en la recursin. O(n)

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

Pseudocdigo Implementacin de rboles binarios de


bsqueda
Tipo
PArbol = Nodo
Nodo = registro
Elemento : TipoElemento
Izquierdo, Derecho : PArbol
fin registro
ABB = Carbol
procedimiento CrearABB (var A)
A := nil
fin procedimiento
funcion Buscar (x, A) : PArbol
si A = nil entonces devolver nil
sino si x = A .Elemento entonces devolver A
sino si x < A .Elemento entonces
devolver Buscar (x, A .Izquierdo)
sino devolver Buscar (x, A .Derecho)
fin funcion
funcion BuscarMin (A) : PArbol
si A = nil entonces devolver nil
sino si A.Izquierdo = nil entonces devolver A
sino devolver BuscarMin (A .Izquierdo)
fin funcion
procedimiento Insertar (x, var A)
si A = nil entonces
nuevo (A);
si A = nil entonces error sin memoria
sino
A .Elemento := x;
A .Izquierdo := nil;
A .Derecho := nil
sino si x < A.Elemento entonces
Insertar (x, A .Izquierdo)
sino si x > A .Elemento entonces
Insertar (x, A .Derecho)
{ si x = A .Elemento : nada }
fin procedimiento
procedimiento Eliminar (x, var A)
si A = nil entonces error no encontrado
sino si x < A .Elemento entonces
Eliminar (x, A .Izquierdo)
sino si x > A .Elemento entonces

Pgina 19 de 91

Eliminar (x, A .Derecho)


sino { x = A .Elemento }
si A .Izquierdo = nil entonces
tmp := A; A := A .Derecho; liberar (tmp)
sino si A .Derecho = nil entonces
tmp := A; A := A .Izquierdo; liberar (tmp)
sino tmp := BuscarMin (A.Derecho);
A .Elemento := tmp .Elemento;
Eliminar (A .Elemento, A .Derecho)
fin procedimiento
//Recorridos de un rbol
//En Orden
procedimiento Visualizar (A)
si A <> nil entonces
Visualizar (A .Izquierdo);
Escribir (A .Elemento);
Visualizar (A .Derecho)
fin procedimiento
//Post-Orden
funcion Altura (A) : numero
si A = nil entonces devolver -1
sino devolver 1 + max (Altura (A .Izquierdo), Altura
(A .Derecho))
fin funcion

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

Implementacin en C++
//El siguiente cdigo en lenguaje C muestra cmo realizar
una bsqueda en un ABB
//Buscar
int buscar(tArbol *a, int elem)
{
if (a == NULL)
return 0;
else if (a->clave < elem)
return buscar(a->hDerecho, elem);
else if (a->clave > elem)
return buscar(a->hIzquierdo, elem);
else
return 1;
}
data abb_search(abb t,key k) {
abb p;
data e;
e=NULL;
p=t;
if (!abb_isEmpty(p))
{
while (!abb_isEmpty(p) && (p->k!=k) )
{
if (k < p->k)
{
p=p->l;
}
if (p->k < k)
{
p=p->r;
}
}
if (!abb_isEmpty(p) &&(p->d!=NULL) )
{
e=data_copy(p->d);
}
}
return e;
}
//Insertar
void insertar(tArbol **a, int elem)
{
if (*a == NULL)
{

Pgina 21 de 91

*a = (tArbol *) malloc(sizeof(tArbol));
(*a)->clave = elem;
(*a)->hIzquierdo = NULL;
(*a)->hDerecho = NULL;
}
else if ((*a)->clave < elem)
insertar(&(*a)->hDerecho, elem);
else if ((*a)->clave > elem)
insertar(&(*a)->hIzquierdo, elem);
}
//Borrado
void borrar(tArbol **a, int elem)
{
void reemplazar(tArbol **a, tArbol **aux);
tArbol *aux;
if (*a == NULL)
return;
if ((*a)->clave < elem)
borrar(&(*a)->hDerecho, elem);
else if ((*a)->clave > elem)
borrar(&(*a)->hIzquierdo, elem);
else if ((*a)->clave == elem)
{
aux = *a;
if ((*a)->hIzquierdo == NULL)
*a = (*a)->hDerecho;
else if ((*a)->hDerecho == NULL)
*a = (*a)->hIzquierdo;
else
reemplazar(&(*a)->hIzquierdo, &aux);
free(aux);
}
}
void reemplazar(tArbol **a, tArbol **aux)
{
if ((*a)->hDerecho == NULL)
{
(*aux)->clave = (*a)->clave;
*aux = *a;
*a = (*a)->hIzquierdo;
}
else
reemplazar(&(*a)->hDerecho, aux);
}

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

//ABB
#include <iostream>
using namespace std;
class ArbolABB {
private:
//// Clase local de Lista para Nodo de ArbolBinario:
class Nodo {
public:
// Constructor:
Nodo(const int dat, Nodo *izq=NULL, Nodo *der=NULL)
:
dato(dat), izquierdo(izq), derecho(der) {}
// Miembros:
int dato;
Nodo *izquierdo;
Nodo *derecho;
};
// Punteros de la lista, para cabeza y nodo actual:
Nodo *raiz;
Nodo *actual;
int contador;
int altura;
public:
// Constructor y destructor bsicos:
ArbolABB() : raiz(NULL), actual(NULL) {}
~ArbolABB() { Podar(raiz); }
// Insertar en rbol ordenado:
void Insertar(const int dat);
// Borrar un elemento del rbol:
void Borrar(const int dat);
// Funcin de bsqueda:
bool Buscar(const int dat);
// Comprobar si el rbol est vaco:
bool Vacio(Nodo *r) { return r==NULL; }
// Comprobar si es un nodo hoja:
bool EsHoja(Nodo *r) { return !r->derecho && !r>izquierdo; }
// Contar nmero de nodos:
const int NumeroNodos();
const int AlturaArbol();
// Calcular altura de un int:
int Altura(const int dat);
// Devolver referencia al int del nodo actual:
int &ValorActual() { return actual->dato; }
// Moverse al nodo raiz:
void Raiz() { actual = raiz; }
// Aplicar una funcin a cada elemento del rbol:

Pgina 23 de 91

void InOrden(void (*func)(int&) , Nodo *nodo=NULL,


bool r=true);
void PreOrden(void (*func)(int&) , Nodo *nodo=NULL,
bool r=true);
void PostOrden(void (*func)(int&) , Nodo *nodo=NULL,
bool r=true);
private:
// Funciones auxiliares
void Podar(Nodo* &);
void auxContador(Nodo*);
void auxAltura(Nodo*, int);
};
// Poda: borrar todos los nodos a partir de uno, incluido
void ArbolABB::Podar(Nodo* &nodo)
{
// Algoritmo recursivo, recorrido en postorden
if(nodo) {
Podar(nodo->izquierdo); // Podar izquierdo
Podar(nodo->derecho);
// Podar derecho
delete nodo;
// Eliminar nodo
nodo = NULL;
}
}
// Insertar un int en el rbol ABB
void ArbolABB::Insertar(const int dat)
{
Nodo *padre = NULL;
actual = raiz;
// Buscar el int en el rbol, manteniendo un puntero
al nodo padre
while(!Vacio(actual) && dat != actual->dato) {
padre = actual;
if(dat > actual->dato) actual = actual->derecho;
else if(dat < actual->dato) actual = actual>izquierdo;
}
// Si se ha encontrado el elemento, regresar sin
insertar
if(!Vacio(actual)) return;
// Si padre es NULL, entonces el rbol estaba vaco,
el nuevo nodo ser
// el nodo raiz
if(Vacio(padre)) raiz = new Nodo(dat);
// Si el int es menor que el que contiene el nodo
padre, lo insertamos
// en la rama izquierda

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

else if(dat < padre->dato) padre->izquierdo = new


Nodo(dat);
// Si el int es mayor que el que contiene el nodo
padre, lo insertamos
// en la rama derecha
else if(dat > padre->dato) padre->derecho = new
Nodo(dat);
}
// Eliminar un elemento de un rbol ABB
void ArbolABB::Borrar(const int dat)
{
Nodo *padre = NULL;
Nodo *nodo;
int aux;
actual = raiz;
// Mientras sea posible que el valor est en el rbol
while(!Vacio(actual)) {
if(dat == actual->dato) { // Si el valor est en el
nodo actual
if(EsHoja(actual)) { // Y si adems es un nodo
hoja: lo borramos
if(padre) // Si tiene padre (no es el nodo
raiz)
// Anulamos el puntero que le hace
referencia
if(padre->derecho == actual) padre>derecho = NULL;
else if(padre->izquierdo == actual) padre>izquierdo = NULL;
delete actual; // Borrar el nodo
actual = NULL;
return;
}
else { // Si el valor est en el nodo actual,
pero no es hoja
// Buscar nodo
padre = actual;
// Buscar nodo ms izquierdo de rama derecha
if(actual->derecho) {
nodo = actual->derecho;
while(nodo->izquierdo) {
padre = nodo;
nodo = nodo->izquierdo;
}
}
// O buscar nodo ms derecho de rama
izquierda
else {
nodo = actual->izquierdo;

Pgina 25 de 91

while(nodo->derecho) {
padre = nodo;
nodo = nodo->derecho;
}
}
// Intercambiar valores de no a borrar u nodo
encontrado
// y continuar, cerrando el bucle. El nodo
encontrado no tiene
// por qu ser un nodo hoja, cerrando el
bucle nos aseguramos
// de que slo se eliminan nodos hoja.
aux = actual->dato;
actual->dato = nodo->dato;
nodo->dato = aux;
actual = nodo;
}
}
else { // Todava no hemos encontrado el valor,
seguir buscndolo
padre = actual;
if(dat > actual->dato) actual = actual->derecho;
else if(dat < actual->dato) actual = actual>izquierdo;
}
}
}
// Recorrido de rbol en inorden, aplicamos la funcin
func, que tiene
// el prototipo:
// void func(int&);
void ArbolABB::InOrden(void (*func)(int&) , Nodo *nodo,
bool r)
{
if(r) nodo = raiz;
if(nodo->izquierdo) InOrden(func, nodo->izquierdo,
false);
func(nodo->dato);
if(nodo->derecho) InOrden(func, nodo->derecho, false);
}
// Recorrido de rbol en preorden, aplicamos la funcin
func, que tiene
// el prototipo:
// void func(int&);
void ArbolABB::PreOrden(void (*func)(int&), Nodo *nodo,
bool r)
{
if(r) nodo = raiz;
func(nodo->dato);

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

if(nodo->izquierdo) PreOrden(func, nodo->izquierdo,


false);
if(nodo->derecho) PreOrden(func, nodo->derecho,
false);
}
// Recorrido de rbol en postorden, aplicamos la funcin
func, que tiene
// el prototipo:
// void func(int&);
void ArbolABB::PostOrden(void (*func)(int&), Nodo *nodo,
bool r)
{
if(r) nodo = raiz;
if(nodo->izquierdo) PostOrden(func, nodo->izquierdo,
false);
if(nodo->derecho) PostOrden(func, nodo->derecho,
false);
func(nodo->dato);
}
// Buscar un valor en el rbol
bool ArbolABB::Buscar(const int dat)
{
actual = raiz;
// Todava puede aparecer, ya que quedan nodos por
mirar
while(!Vacio(actual)) {
if(dat == actual->dato) return true; // int
encontrado
else if(dat > actual->dato) actual = actual>derecho; // Seguir
else if(dat < actual->dato) actual = actual>izquierdo;
}
return false; // No est en rbol
}
// Calcular la altura del nodo que contiene el int dat
int ArbolABB::Altura(const int dat)
{
int altura = 0;
actual = raiz;
// Todava puede aparecer, ya que quedan nodos por
mirar
while(!Vacio(actual)) {
if(dat == actual->dato) return altura; // int
encontrado
else {

Pgina 27 de 91

altura++; // Incrementamos la altura, seguimos


buscando
if(dat > actual->dato) actual = actual->derecho;
else if(dat < actual->dato) actual = actual>izquierdo;
}
}
return -1; // No est en rbol
}
// Contar el nmero de nodos
const int ArbolABB::NumeroNodos()
{
contador = 0;
auxContador(raiz); // FUncin auxiliar
return contador;
}
// Funcin auxiliar para contar nodos. Funcin recursiva
de recorrido en
//
preorden, el proceso es aumentar el contador
void ArbolABB::auxContador(Nodo *nodo)
{
contador++; // Otro nodo
// Continuar recorrido
if(nodo->izquierdo) auxContador(nodo->izquierdo);
if(nodo->derecho)
auxContador(nodo->derecho);
}
// Calcular la altura del rbol, que es la altura del
nodo de mayor altura.
const int ArbolABB::AlturaArbol()
{
altura = 0;
auxAltura(raiz, 0); // Funcin auxiliar
return altura;
}
// Funcin auxiliar para calcular altura. Funcin
recursiva de recorrido en
// postorden, el proceso es actualizar la altura slo en
nodos hojas de mayor
// altura de la mxima actual
void ArbolABB::auxAltura(Nodo *nodo, int a)
{
// Recorrido postorden
if(nodo->izquierdo) auxAltura(nodo->izquierdo, a+1);
if(nodo->derecho)
auxAltura(nodo->derecho, a+1);

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

// Proceso, si es un nodo hoja, y su altura es mayor


que la actual del
// rbol, actualizamos la altura actual del rbol
if(EsHoja(nodo) && a > altura) altura = a;
}
// Funcin de prueba para recorridos del rbol
void Mostrar(int &d)
{
cout << d << ",";
}
int main()
{
// Un rbol de enteros
ArbolABB ArbolInt;
// Insercin de nodos en rbol:
ArbolInt.Insertar(10);
ArbolInt.Insertar(5);
ArbolInt.Insertar(12);
ArbolInt.Insertar(4);
ArbolInt.Insertar(7);
ArbolInt.Insertar(3);
ArbolInt.Insertar(6);
ArbolInt.Insertar(9);
ArbolInt.Insertar(8);
ArbolInt.Insertar(11);
ArbolInt.Insertar(14);
ArbolInt.Insertar(13);
ArbolInt.Insertar(2);
ArbolInt.Insertar(1);
ArbolInt.Insertar(15);
ArbolInt.Insertar(10);
ArbolInt.Insertar(17);
ArbolInt.Insertar(18);
ArbolInt.Insertar(16);
cout << "Altura de arbol " << ArbolInt.AlturaArbol()
<< endl;
// Mostrar el rbol en tres ordenes distintos:
cout << "InOrden: ";
ArbolInt.InOrden(Mostrar);
cout << endl;
cout << "PreOrden: ";
ArbolInt.PreOrden(Mostrar);
cout << endl;
cout << "PostOrden: ";
ArbolInt.PostOrden(Mostrar);
cout << endl;

Pgina 29 de 91

// Borraremos algunos elementos:


cout << "N nodos: " << ArbolInt.NumeroNodos() << endl;
ArbolInt.Borrar(5);
cout << "Borrar
5: ";
ArbolInt.InOrden(Mostrar);
cout << endl;
ArbolInt.Borrar(8);
cout << "Borrar
8: ";
ArbolInt.InOrden(Mostrar);
cout << endl;
ArbolInt.Borrar(15);
cout << "Borrar 15: ";
ArbolInt.InOrden(Mostrar);
cout << endl;
ArbolInt.Borrar(245);
cout << "Borrar 245: ";
ArbolInt.InOrden(Mostrar);
cout << endl;
ArbolInt.Borrar(4);
cout << "Borrar
4: ";
ArbolInt.InOrden(Mostrar);
ArbolInt.Borrar(17);
cout << endl;
cout << "Borrar 17: ";
ArbolInt.InOrden(Mostrar);
cout << endl;
// Veamos algunos parmetros
cout << "N nodos: " << ArbolInt.NumeroNodos() << endl;
cout << "Altura de 1 " << ArbolInt.Altura(1) << endl;
cout << "Altura de 10 " << ArbolInt.Altura(10) <<
endl;
cout << "Altura de arbol " << ArbolInt.AlturaArbol()
<< endl;
cin.get();
return 0;
}

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

Implementacin en Java
package jerarquicos; import excepciones.*;
public class ArbolBinarioBusqueda
{
NodoBinario raiz;
long numTotalInserciones, numTotalComparaciones;
public ArbolBinarioBusqueda()
{
raiz = null;
numTotalInserciones = 0;
numTotalComparaciones = 0;
}
public boolean esVacio(){return raiz == null;}
public String toString()
{
if ( this.raiz != null ) return
raiz.imprimirInOrden();
else return "";
}
public String imprimirPorNiveles ()
{
if ( this.raiz != null ) return
raiz.imprimirPorNiveles();
else return "";
}
public int tamanyo() { return NodoBinario.tamanyo(raiz);
}
public int altura() { return NodoBinario.altura(raiz);}
public double eMC(){ return
((double)numTotalComparaciones)/numTotalInserciones;}
protected NodoBinario buscar(Object clave, NodoBinario n)
throws ElementoNoEncontrado
{
if ( n == null ) throw new
ElementoNoEncontrado("**al buscar: "+clave+" no esta");
int resC = ((Comparable)n.dato).compareTo(clave) ;
if ( resC < 0 ) return buscar( clave, n.der
) ;
else if ( resC > 0 ) return buscar( clave,
n.izq ) ;
else return n;
}
protected NodoBinario insertar(Object clave, NodoBinario
n) throws ElementoDuplicado
{
if ( n == null )
{
numTotalInserciones++; return new
NodoBinario(clave);
}

Pgina 31 de 91

else {
int resC =
((Comparable)n.dato).compareTo(clave) ;
numTotalComparaciones++;
if ( resC < 0 ) n.der = insertar(clave,
n.der );
else if ( resC > 0 ) n.izq = insertar(clave,
n.izq ) ;
else throw new ElementoDuplicado("**al insertar:
"+clave+" ya esta");
return n ;
}
}
protected NodoBinario insertarTodos(Object clave,
NodoBinario n)
{
if ( n == null ) return new NodoBinario(clave);
else{
int resC =
((Comparable)n.dato).compareTo(clave) ;
if ( resC < 0 ) n.der = insertarTodos(clave,
n.der );
else n.izq = insertarTodos(clave, n.izq ) ;
return n ;
}
}
protected NodoBinario eliminar(Object clave, NodoBinario
n) throws ElementoNoEncontrado {
if ( n == null ) throw new
ElementoNoEncontrado("**al eliminar: "+clave+" no
esta");
int resC = ((Comparable)n.dato).compareTo(clave) ;
if ( resC < 0 ) n.der = eliminar( clave,
n.der );
else if ( resC > 0 ) n.izq = eliminar(
clave, n.izq ) ;
else if ( n.izq != null && n.der != null )
{
n.dato = buscarMin(n.der).dato; n.der =
eliminarMin(n.der);
} else n = ( n.izq != null ) ? n.izq: n.der ;
return n ;
}
protected NodoBinario eliminarMin(NodoBinario n)
{
if ( n.izq != null ) n.izq = eliminarMin(n.izq);
else n = n.der;
return n;
}
protected NodoBinario buscarMin (NodoBinario n)
{

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

while (n.izq != null) n = n.izq;


return n;
}
}
public class ABB {
Nodo raiz;
public ABB() {
raiz = null;
}
public ABB(Nodo raiz) {
this.raiz = raiz;
}
// otros metodos .....
public int altura() {
return altura(raiz);
}
private int altura(Nodo nodo) {
if (nodo == null)
return 0;
int altizq = altura(nodo.izq);
int altder = altura(nodo.der);
return 1 + Math.max(altizq, altder);
}
}

Pgina 33 de 91

rboles AVL
Un rbol AVL (llamado as por las iniciales de sus inventores: Adelson-Velskii
y Landis) es un rbol binario de bsqueda en el que para cada nodo, las
alturas de sus subrboles izquierdo y derecho no difieren en ms de 1.
No se trata de rboles perfectamente equilibrados, pero s son lo
suficientemente equilibrados como para que su comportamiento sea lo
bastante bueno como para usarlos donde los ABB no garantizan tiempos de
bsqueda ptimos.
El algoritmo para mantener un rbol AVL equilibrado se basa en
reequilibrados locales, de modo que no es necesario explorar todo el rbol
despus de cada insercin o borrado.
Un nodo es la unidad bsica sobre la que se construye un rbol y puede tener
cero o ms nodos hijos conectados a l, hasta un determinado numero de
nodos.
Los nodos pueden ser:
Raz, es el nodo que no tiene padre o el que inicia el rbol.
Padre, si desde el nodo a existe un enlace hasta el nodo b (decimos
que b es hijo de a).
Hoja, es un nodo que no tiene hijos.
La nica diferencia de los nodos de un rbol AVL con los de un rbol binario
comn, es la variable altura donde en la estructura nodo, la altura de la
rama izquierda no difiere en ms de una unidad de la altura de la rama
derecha. Con respecto a los enlaces, cada nodo se puede descomponer en 3
partes, una que guarda la informacin o datos y otras dos que permiten los
enlaces con hijos o subrboles izquierdo y derecho.
Los nodos de un rbol pueden almacenar cualquier tipo de dato. En nuestro
caso usaremos datos de tipo entero.
Para que el tiempo de ejecucin de esas funciones no sea O (n),
redefiniremos la funcin aprovechando el campo altura que tiene cada nodo
del rbol.
Un rbol AVL es un rbol 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 adems debe cumplir con la
propiedad de equilibrio que esta dado por la diferencia entre las alturas

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

del rbol derecho y el izquierdo. Por definicin, para un rbol AVL, este valor
debe ser -1, 0 1.
FE = altura subrbol derecho - altura subrbol izquierdo.
Gracias a esta forma de equilibrio (o balanceo), la complejidad de una
bsqueda en uno de estos rboles se mantiene siempre en orden de
complejidad O (Log ( n ) ).
Para conseguir esta propiedad de equilibrio, la insercin y el borrado de los
nodos se han de realizar de una forma especial. Si al realizar una operacin
de insercin o borrado se rompe la condicin de equilibrio, hay que realizar
una serie de rotaciones de los nodos. Como es una estructura no lineal, las
operaciones sobre estas estructuras no debern recorrer mucho para hallar el
elemento deseado.
Un rbol se puede recorrer de las siguientes formas:
Preorden, postorden, inorden y un recorrido por
niveles.
La profundidad de un rbol es la longitud del camino
que va desde la raz hasta el nodo.

Operaciones comunes en los rboles de bsqueda AVL son:


Es vaco: Utilizamos un mtodo de tipo bolean, no recursivo, que
retorna true si la raz es null
Vaciar el rbol: Utilizamos un mtodo no recursivo que solamente
le asigna un valor null al nodo raz, por medio de el construimos un
rbol vaco o lo vaciamos.
Imprimir los recorridos en preorden, enorden y postorden, sus
nombres derivan del lugar en que se visita la raz con respecto a sus
subrboles.
Imprimir preorden: consiste en recorrer en primer lugar la raz y
luego cada uno de los hijos (o subrboles).
Imprimir enorden: consiste en recorrer en primer lugar los hijos
(o subrbol) de la rama izquierda, luego la raz y luego cada uno de
los hijos de la rama derecha (o subrbol).
Imprimir postorden: consiste en recorrer en primer lugar cada
uno de los hijos (o subrboles) y por ultimo la raz.

Pgina 35 de 91

En estas operaciones, en la clase AvlTreeNode, por medio de mtodos


recursivos, se muestra primero la raz o en la mitad o al final y si el rbol no
esta vaco recorre el rbol en preorden, teniendo en cuenta la posicin de la
raiz hace los recorridos en enorden o postorden hasta llegar a cada una de
sus hojas izquierda y derecha o raz, estos mtodos se invocan en la clase
AvlTree.
Tamao del rbol: El tamao de un rbol Binario de bsqueda AVL es el
tamao de su nodo raz.
En la clase AvlTreeNode creamos un mtodo recursivo que es invocado en la
clase AvlTree con el que obtenemos la cantidad de nodos de cada rama o
subrboles ms el nodo raz.
La altura o nivel o profundidad de un nodo es la longitud del camino que
va desde el nodo hasta la hoja ms profunda bajo l. Todo nodo hoja tiene
altura cero. Para un rbol que consta slo del nodo raz su altura es 0.
En la clase AvlTreeNode calculamos la altura de un nodo por medio de un
mtodo recursivo (altura) el cual es llamado en la clase AvlTree pasando
como parmetro la raz la que devuelve -1 si es null o la altura del rbol de
tener enlace a otro(s) nodo(s). Por esto se define la altura de un rbol vaco
como -1. (1 1 = 0).
Insertar nodos: El mtodo insertar un nodo permite aadir un nodo al
rbol.
La insercin en un rbol de AVL puede ser realizada insertando el valor dado
en el rbol como si fuera un rbol de bsqueda binario desequilibrado y
despus retrocediendo hacia la raz, rotando sobre cualquier nodo que pueda
haberse desequilibrado durante la insercin.
Dado que como mucho un nodo es rotado 1,5 veces log n en la vuelta hacia
la raz, y cada rotacin AVL tarda el mismo tiempo, el proceso de insercin
tarda un tiempo total de O (Log n).
La clase AvlTree hace un llamado al mtodo recursivo AvlTreeNode insertar
con parmetros comparable x y raz t. Si t no tiene hijos crea el nuevo nodo x
con enlaces null. Si t tiene hijos, compara los datos x y t, para definir en que
posicin ubica el nodo (izquierda o derecha), para cumplir con la propiedad
de equilibrio, si la diferencia entre niveles izquierdo y derecho es 2, hace las

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

correspondientes rotaciones por medio de los mtodos de giroConHijoIzq o


giroConHijoDer para por ultimo recalcular la altura del rbol.
Buscar un elemento cualquiera en un subrbol, el mayor o menor y
la raz:
Las bsquedas se realizan de la misma manera que en los ABB, pero al estar
el rbol equilibrado la complejidad de la bsqueda nunca exceder de O
(Log n).
Podemos buscar un nodo de un subrbol, en la clase AvlTree, pasando como
parmetros a la clase AvlTreeNode x que es nodo a buscar y el parmetro t
del nodo raz. Este mtodo retorna si se encuentra o no.
Otra operacin es el buscar un nodo en el rbol iniciando su recorrido en la
raz.

Borrar o eliminar un elemento:


El problema de la eliminacin puede resolverse en O (Log n) pasos. Una
eliminacin trae consigo una disminucin de la altura de la rama donde se
extrajo y tendr como efecto un cambio en el factor de equilibrio del nodo
padre de la rama en cuestin, pudiendo necesitarse una rotacin.
Esta disminucin de la altura y la correccin de los factores de equilibrio con
sus posibles rotaciones asociadas pueden propagarse hasta la raz.
Llama al mtodo recursivo eliminarRec pasando el parmetro x y el nodo
raz.
Eliminar un subrbol, eliminar un nodo con mayor o menor dato de
un subrbol (algunas veces llamada podar):
Mtodo Recursivo que elimina de un subrbol el nodo con dato x. r es la raz
del subrbol. Retorna la nueva raz.
Mtodo Recursivo que elimina de un subrbol el nodo que tiene el mayor
dato. r es la raz del subrbol. Retorna la nueva raz.
Mtodo Recursivo que elimina de un subrbol el nodo que tiene el menor
dato. r es la raz del subrbol. Retorna la nueva raz.

Pgina 37 de 91

Aadir un subrbol (algunas veces llamada injertar).


La profundidad del rbol tendr orden de complejidad O (Log (n))
Rotaciones: se utilizan para balancear el rbol. Existen cuatro tipos de
rotaciones, dos simples y dos dobles. Los mtodos empleados para los cuatro
giros solo varan en el sentido del giro.
Rotar con hijo derecho y Rotar con hijo izquierdo:
Esta rotacin se usar cuando el subrbol derecho de un nodo sea 2
unidades ms alto que el izquierdo, es decir, cuando su FE sea de 2. Y
adems, la raz del subrbol derecho tenga una FE de 1, es decir, que est
cargado a la derecha.

Procederemos del siguiente modo:


Llamaremos P al nodo que muestra el desequilibrio, el que tiene una FE de 2.
Y llamaremos Q al nodo raz del subrbol derecho de P. Adems, llamaremos
A al subrbol izquierdo de P, B al subrbol izquierdo de Q y C al subrbol
derecho de Q.
En el grfico que puede observar que tanto A como B tienen la misma altura
(n), y C es una unidad mayor (n+1). Esto hace que el FE de Q sea 1, la altura
del subrbol que tiene Q como raz es (n+2) y por lo tanto el FE de P es 2.
1. Pasamos el subrbol izquierdo del nodo Q como subrbol derecho de
P. Esto mantiene el rbol como ABB, ya que todos los valores a la
izquierda de Q siguen estando a la derecha de P.
2. El rbol P pasa a ser el subrbol izquierdo del nodo Q.
3. Ahora, el nodo Q pasa a tomar la posicin del nodo P, es decir,
hacemos que la entrada al rbol sea el nodo Q, en lugar del nodo P.
Previamente, P puede que fuese un rbol completo o un subrbol de
otro nodo de menor altura.

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

En el rbol resultante se puede ver que tanto P como Q quedan equilibrados


en cuanto a altura. En el caso de P porque sus dos subrboles tienen la
misma altura (n), en el caso de Q, porque su subrbol izquierdo A tiene una
altura (n+1) y su subrbol derecho tambin, ya que a P se aade la altura de
cualquiera de sus subrboles.

Recibe un dato de tipo nodo (k1 es el que referencia a los hijos de una rama
derecha), y retorna una variable tipo nodo, hace el recorrido por la rama
izquierda y hace los cambios necesarios. Modifica la altura del rbol con la
variable altura que es referencia de la clase nodo; primero con los izquierdos
y despus con los derechos y retorna el giro final despus de equilibrar toda
la rama.

Pgina 39 de 91

Rotacin doble a la izquierda y Rotacin doble a la derecha:


Esta rotacin se usar cuando el subrbol izquierdo de un nodo sea 2
unidades ms alto que el derecho, es decir, cuando su FE sea de -2. Y
adems, la raz del subrbol izquierdo tenga una FE de 1, es decir, que est
cargado a la derecha.

Este es uno de los posibles rboles que pueden presentar esta estructura,
pero hay otras dos posibilidades. El nodo R puede tener una FE de -1, 0 1.
En cada uno de esos casos los rboles izquierdo y derecho de R (B y C)
pueden tener alturas de n y n-1, n y n, o n-1 y n, respectivamente.
El modo de realizar la rotacin es independiente de la estructura del rbol R,
cualquiera de las tres produce resultados equivalentes. Haremos el anlisis
para el caso en que FE sea -1.
En este caso tendremos que realizar dos rotaciones.
Llamaremos P al nodo que muestra el desequilibrio, el que tiene una FE
de -2. Llamaremos Q al nodo raz del subrbol izquierdo de P, y R al nodo raz
del subrbol derecho de Q.
1. Haremos una rotacin simple de Q a la izquierda.
2. Despus, haremos una rotacin simple de P a la derecha.
Con ms detalle, procederemos del siguiente modo:
1. Pasamos el subrbol izquierdo del nodo R como subrbol derecho de
Q. Esto mantiene el rbol como ABB, ya que todos los valores a la
izquierda de R siguen estando a la derecha de Q.
2. Ahora, el nodo R pasa a tomar la posicin del nodo Q, es decir,
hacemos que la raz del subrbol izquierdo de P sea el nodo R en lugar
de Q.
3. El rbol Q pasa a ser el subrbol izquierdo del nodo R.

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

4. Pasamos el subrbol derecho del nodo R como subrbol izquierdo de


P. Esto mantiene el rbol como ABB, ya que todos los valores a la
derecha de R siguen estando a la izquierda de P.
5. Ahora, el nodo R pasa a tomar la posicin del nodo P, es decir,
hacemos que la entrada al rbol sea el nodo R, en lugar del nodo P.
Como en los casos anteriores, previamente, P puede que fuese un
rbol completo o un subrbol de otro nodo de menor altura.
6. El rbol P pasa a ser el subrbol derecho del nodo R.

Orden de Complejidad rboles Avl:


Estos rboles se mantienen balanceados en cualquier operacin que se
realiza sobre ellos, ya sea insercin o eliminacin, pero estas dos operaciones
no son tan simples; adems se debe garantizar que el orden de complejidad
de la altura del rbol es O (log n) , y asumiendo en el peor de los casos las
operaciones de bsqueda sean O (log n) .
En el rbol AVL la insercin (sin eliminacin), se debe encontrar el sitio
adecuado para poder insertar el dato esta bsqueda es de orden de
complejidad O (log n) , y la insercin como tal es directa O (1) . La eliminacin
en el peor de los casos, se da cuando el elemento sea una hoja del rbol, en
consecuencia el orden de complejidad es O (log n) .
Se debe tener en cuenta que el orden de complejidad y el tiempo de
ejecucin en un AVL tiene una carga adicional dada por el balanceo que este

Pgina 41 de 91

debe hacer si se hacen eliminaciones e inserciones permanentes, ya que


como se ha mencionado en clase un rbol binario sin balanceo tiende a tener
una altura del orden O ( n ) en caso promedio, si es equilibrado y O (n) sino lo
es.
Balanceo de rboles
El balance de un nodo en un rbol binario, se obtiene calculando la diferencia
de la altura del subrbol izquierdo y la del subrbol derecho. Esta diferencia
segn las propiedades
de los rboles binarios, puede ser:
1, la altura del subrbol izquierdo es mayor que la del derecho.
0, las alturas de los dos subrboles son iguales.
1, la altura del subrbol derecho es mayor que la del izquierdo.
Con el propsito de mejorar los procedimientos de insercin y ordenacin en
rboles AVL, se introduce un nuevo parmetro, denominado Factor de
Balance (FB), que especifica para cada nodo la diferencia de la altura entre
el subrbol izquierdo y derecho.
FB = Hizq Hder
Algunos autores utilizan la notacin:
- (0), perfectamente balanceado
\ (-1), cargado a la derecha.
/ (1), cargado a la izquierda.

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

Implementacin en C++
//Arbol AVL en C++
#include <iostream>
using namespace std;
class AVL;
// Clase Nodo de Arbol AVL:
class Nodo {
public:
// Constructor:
Nodo(const int dat, Nodo *pad=NULL, Nodo *izq=NULL,
Nodo *der=NULL) :
dato(dat), padre(pad), izquierdo(izq), derecho(der),
FE(0) {}
// Miembros:
int dato;
int FE;
Nodo *izquierdo;
Nodo *derecho;
Nodo *padre;
friend class AVL;
};
class AVL {
private:
enum {IZQUIERDO, DERECHO};
// Punteros de la lista, para cabeza y nodo actual:
Nodo *raiz;
Nodo *actual;
int contador;
int altura;
public:
// Constructor y destructor bsicos:
AVL() : raiz(NULL), actual(NULL) {}
~AVL() { Podar(raiz); }
// Insertar en rbol ordenado:
void Insertar(const int dat);
// Borrar un elemento del rbol:
void Borrar(const int dat);
// Funcin de bsqueda:
bool Buscar(const int dat);
// Comprobar si el rbol est vaco:
bool Vacio(Nodo *r) { return r==NULL; }
// Comprobar si es un nodo hoja:
bool EsHoja(Nodo *r) { return !r->derecho && !r>izquierdo; }
// Contar nmero de nodos:

Pgina 43 de 91

const int NumeroNodos();


const int AlturaArbol();
// Calcular altura de un dato:
int Altura(const int dat);
// Devolver referencia al dato del nodo actual:
int &ValorActual() { return actual->dato; }
// Moverse al nodo raiz:
void Raiz() { actual = raiz; }
// Aplicar una funcin a cada elemento del rbol:
void InOrden(void (*func)(int&, int) , Nodo
*nodo=NULL, bool r=true);
void PreOrden(void (*func)(int&, int) , Nodo
*nodo=NULL, bool r=true);
void PostOrden(void (*func)(int&, int) , Nodo
*nodo=NULL, bool r=true);
private:
// Funciones de equilibrado:
void Equilibrar(Nodo *nodo, int, bool);
void RSI(Nodo* nodo);
void RSD(Nodo* nodo);
void RDI(Nodo* nodo);
void RDD(Nodo* nodo);
// Funciones auxiliares
void Podar(Nodo* &);
void auxContador(Nodo*);
void auxAltura(Nodo*, int);
};
// Poda: borrar todos los nodos a partir de uno, incluido
void AVL::Podar(Nodo* &nodo)
{
// Algoritmo recursivo, recorrido en postorden
if(nodo) {
Podar(nodo->izquierdo); // Podar izquierdo
Podar(nodo->derecho);
// Podar derecho
delete nodo;
// Eliminar nodo
nodo = NULL;
}
}
// Insertar un dato en el rbol AVL
void AVL::Insertar(const int dat)
{
Nodo *padre = NULL;
cout << "Insertar: " << dat << endl;
actual = raiz;
// Buscar el dato en el rbol, manteniendo un puntero
al nodo padre
while(!Vacio(actual) && dat != actual->dato) {
padre = actual;

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

if(dat > actual->dato) actual = actual->derecho;


else if(dat < actual->dato) actual = actual>izquierdo;
}
// Si se ha encontrado el elemento, regresar sin
insertar
if(!Vacio(actual)) return;
// Si padre es NULL, entonces el rbol estaba vaco,
el nuevo nodo ser
// el nodo raiz
if(Vacio(padre)) raiz = new Nodo(dat);
// Si el dato es menor que el que contiene el nodo
padre, lo insertamos
// en la rama izquierda
else if(dat < padre->dato) {
padre->izquierdo = new Nodo(dat, padre);
Equilibrar(padre, IZQUIERDO, true);
}
// Si el dato es mayor que el que contiene el nodo
padre, lo insertamos
// en la rama derecha
else if(dat > padre->dato) {
padre->derecho = new Nodo(dat, padre);
Equilibrar(padre, DERECHO, true);
}
}
// Equilibrar rbol AVL partiendo del nodo nuevo
void AVL::Equilibrar(Nodo *nodo, int rama, bool nuevo)
{
bool salir = false;
// Recorrer camino inverso actualizando valores de FE:
while(nodo && !salir) {
if(nuevo)
if(rama == IZQUIERDO) nodo->FE--; // Depende de
si aadimos ...
else
nodo->FE++;
else
if(rama == IZQUIERDO) nodo->FE++; // ... o
borramos
else
nodo->FE--;
if(nodo->FE == 0) salir = true; // La altura de las
rama que
// empieza en nodo
no ha variado,
// salir de
Equilibrar
else if(nodo->FE == -2) { // Rotar a derechas y
salir:

Pgina 45 de 91

if(nodo->izquierdo->FE == 1) RDD(nodo); //
Rotacin doble
else RSD(nodo);
//
Rotacin simple
salir = true;
}
else if(nodo->FE == 2) { // Rotar a izquierdas y
salir:
if(nodo->derecho->FE == -1) RDI(nodo); //
Rotacin doble
else RSI(nodo);
//
Rotacin simple
salir = true;
}
if(nodo->padre)
if(nodo->padre->derecho == nodo) rama = DERECHO;
else rama = IZQUIERDO;
nodo = nodo->padre; // Calcular FE, siguiente nodo
del camino.
}
}
// Rotacin doble a derechas
void AVL::RDD(Nodo* nodo)
{
cout << "RDD" << endl;
Nodo *Padre = nodo->padre;
Nodo *P = nodo;
Nodo *Q = P->izquierdo;
Nodo *R = Q->derecho;
Nodo *B = R->izquierdo;
Nodo *C = R->derecho;
if(Padre)
if(Padre->derecho == nodo) Padre->derecho = R;
else Padre->izquierdo = R;
else raiz = R;
// Reconstruir rbol:
Q->derecho = B;
P->izquierdo = C;
R->izquierdo = Q;
R->derecho = P;
// Reasignar padres:
R->padre = Padre;
P->padre = Q->padre = R;
if(B) B->padre = Q;
if(C) C->padre = P;
// Ajustar valores de FE:

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

switch(R->FE) {
case -1: Q->FE = 0; P->FE = 1; break;
case 0: Q->FE = 0; P->FE = 0; break;
case 1: Q->FE = -1; P->FE = 0; break;
}
R->FE = 0;
}
// Rotacin doble a izquierdas
void AVL::RDI(Nodo* nodo)
{
cout << "RDI" << endl;
Nodo *Padre = nodo->padre;
Nodo *P = nodo;
Nodo *Q = P->derecho;
Nodo *R = Q->izquierdo;
Nodo *B = R->izquierdo;
Nodo *C = R->derecho;
if(Padre)
if(Padre->derecho == nodo) Padre->derecho = R;
else Padre->izquierdo = R;
else raiz = R;
// Reconstruir rbol:
P->derecho = B;
Q->izquierdo = C;
R->izquierdo = P;
R->derecho = Q;
// Reasignar padres:
R->padre = Padre;
P->padre = Q->padre = R;
if(B) B->padre = P;
if(C) C->padre = Q;
// Ajustar valores de FE:
switch(R->FE) {
case -1: P->FE = 0; Q->FE = 1; break;
case 0: P->FE = 0; Q->FE = 0; break;
case 1: P->FE = -1; Q->FE = 0; break;
}
R->FE = 0;
}
// Rotacin simple a derechas
void AVL::RSD(Nodo* nodo)
{
cout << "RSD" << endl;
Nodo *Padre = nodo->padre;
Nodo *P = nodo;

Pgina 47 de 91

Nodo *Q = P->izquierdo;
Nodo *B = Q->derecho;
if(Padre)
if(Padre->derecho == P) Padre->derecho = Q;
else Padre->izquierdo = Q;
else raiz = Q;
// Reconstruir rbol:
P->izquierdo = B;
Q->derecho = P;
// Reasignar padres:
P->padre = Q;
if(B) B->padre = P;
Q->padre = Padre;
// Ajustar valores de FE:
P->FE = 0;
Q->FE = 0;
}
// Rotacin simple a izquierdas
void AVL::RSI(Nodo* nodo)
{
cout << "RSI" << endl;
Nodo *Padre = nodo->padre;
Nodo *P = nodo;
Nodo *Q = P->derecho;
Nodo *B = Q->izquierdo;
if(Padre)
if(Padre->derecho == P) Padre->derecho = Q;
else Padre->izquierdo = Q;
else raiz = Q;
// Reconstruir rbol:
P->derecho = B;
Q->izquierdo = P;
// Reasignar padres:
P->padre = Q;
if(B) B->padre = P;
Q->padre = Padre;
// Ajustar valores de FE:
P->FE = 0;
Q->FE = 0;
}

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

// Eliminar un elemento de un rbol AVL


void AVL::Borrar(const int dat)
{
Nodo *padre = NULL;
Nodo *nodo;
int aux;
actual = raiz;
// Mientras sea posible que el valor est en el rbol
while(!Vacio(actual)) {
if(dat == actual->dato) { // Si el valor est en el
nodo actual
if(EsHoja(actual)) { // Y si adems es un nodo
hoja: lo borramos
if(padre) // Si tiene padre (no es el nodo
raiz)
// Anulamos el puntero que le hace
referencia
if(padre->derecho == actual) padre>derecho = NULL;
else if(padre->izquierdo == actual) padre>izquierdo = NULL;
delete actual; // Borrar el nodo
actual = NULL;
// El nodo padre del actual puede ser ahora
un nodo hoja, por lo tanto su
// FE es cero, pero debemos seguir el camino
a partir de su padre, si existe.
if((padre->derecho == actual && padre->FE ==
1) ||
(padre->izquierdo == actual && padre->FE
== -1)) {
padre->FE = 0;
actual = padre;
padre = actual->padre;
}
if(padre)
if(padre->derecho == actual)
Equilibrar(padre, DERECHO, false);
else
Equilibrar(padre, IZQUIERDO, false);
return;
}
else { // Si el valor est en el nodo actual,
pero no es hoja
// Buscar nodo
padre = actual;
// Buscar nodo ms izquierdo de rama derecha
if(actual->derecho) {
nodo = actual->derecho;
while(nodo->izquierdo) {

Pgina 49 de 91

padre = nodo;
nodo = nodo->izquierdo;
}
}
// O buscar nodo ms derecho de rama
izquierda
else {
nodo = actual->izquierdo;
while(nodo->derecho) {
padre = nodo;
nodo = nodo->derecho;
}
}
// Intercambiar valores de no a borrar u nodo
encontrado
// y continuar, cerrando el bucle. El nodo
encontrado no tiene
// por qu ser un nodo hoja, cerrando el
bucle nos aseguramos
// de que slo se eliminan nodos hoja.
aux = actual->dato;
actual->dato = nodo->dato;
nodo->dato = aux;
actual = nodo;
}
}
else { // Todava no hemos encontrado el valor,
seguir buscndolo
padre = actual;
if(dat > actual->dato) actual = actual->derecho;
else if(dat < actual->dato) actual = actual>izquierdo;
}
}
}
// Recorrido de rbol en inorden, aplicamos la funcin
func, que tiene
// el prototipo:
// void func(int&, int);
void AVL::InOrden(void (*func)(int&, int) , Nodo *nodo,
bool r)
{
if(r) nodo = raiz;
if(nodo->izquierdo) InOrden(func, nodo->izquierdo,
false);
func(nodo->dato, nodo->FE);
if(nodo->derecho) InOrden(func, nodo->derecho, false);
}

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

// Recorrido de rbol en preorden, aplicamos la funcin


func, que tiene
// el prototipo:
// void func(int&, int);
void AVL::PreOrden(void (*func)(int&, int), Nodo *nodo,
bool r)
{
if(r) nodo = raiz;
func(nodo->dato, nodo->FE);
if(nodo->izquierdo) PreOrden(func, nodo->izquierdo,
false);
if(nodo->derecho) PreOrden(func, nodo->derecho,
false);
}
// Recorrido de rbol en postorden, aplicamos la funcin
func, que tiene
// el prototipo:
// void func(int&, int);
void AVL::PostOrden(void (*func)(int&, int), Nodo *nodo,
bool r)
{
if(r) nodo = raiz;
if(nodo->izquierdo) PostOrden(func, nodo->izquierdo,
false);
if(nodo->derecho) PostOrden(func, nodo->derecho,
false);
func(nodo->dato, nodo->FE);
}
// Buscar un valor en el rbol
bool AVL::Buscar(const int dat)
{
actual = raiz;
// Todava puede aparecer, ya que quedan nodos por
mirar
while(!Vacio(actual)) {
if(dat == actual->dato) return true; // dato
encontrado
else if(dat > actual->dato) actual = actual>derecho; // Seguir
else if(dat < actual->dato) actual = actual>izquierdo;
}
return false; // No est en rbol
}
// Calcular la altura del nodo que contiene el dato dat
int AVL::Altura(const int dat)
{

Pgina 51 de 91

int altura = 0;
actual = raiz;
// Todava puede aparecer, ya que quedan nodos por
mirar
while(!Vacio(actual)) {
if(dat == actual->dato) return altura; // dato
encontrado
else {
altura++; // Incrementamos la altura, seguimos
buscando
if(dat > actual->dato) actual = actual->derecho;
else if(dat < actual->dato) actual = actual>izquierdo;
}
}
return -1; // No est en rbol
}
// Contar el nmero de nodos
const int AVL::NumeroNodos()
{
contador = 0;
auxContador(raiz); // FUncin auxiliar
return contador;
}
// Funcin auxiliar para contar nodos. Funcin recursiva
de recorrido en
//
preorden, el proceso es aumentar el contador
void AVL::auxContador(Nodo *nodo)
{
contador++; // Otro nodo
// Continuar recorrido
if(nodo->izquierdo) auxContador(nodo->izquierdo);
if(nodo->derecho)
auxContador(nodo->derecho);
}
// Calcular la altura del rbol, que es la altura del
nodo de mayor altura.
const int AVL::AlturaArbol()
{
altura = 0;
auxAltura(raiz, 0); // Funcin auxiliar
return altura;
}
// Funcin auxiliar para calcular altura. Funcin
recursiva de recorrido en

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

// postorden, el proceso es actualizar la altura slo en


nodos hojas de mayor
// altura de la mxima actual
void AVL::auxAltura(Nodo *nodo, int a)
{
// Recorrido postorden
if(nodo->izquierdo) auxAltura(nodo->izquierdo, a+1);
if(nodo->derecho)
auxAltura(nodo->derecho, a+1);
// Proceso, si es un nodo hoja, y su altura es mayor
que la actual del
// rbol, actualizamos la altura actual del rbol
if(EsHoja(nodo) && a > altura) altura = a;
}
// Funcin de prueba para recorridos del rbol
void Mostrar(int &d, int FE)
{
cout << d << "(" << FE << "),";
}
int main()
{
// Un rbol de enteros
AVL ArbolInt;
/*

// Insercin de nodos en rbol:


ArbolInt.Insertar(15);
ArbolInt.Insertar(4);
ArbolInt.Insertar(20);
ArbolInt.Insertar(3);
ArbolInt.Insertar(25);
ArbolInt.Insertar(6);
ArbolInt.Insertar(8);*/
ArbolInt.Insertar(1);
ArbolInt.Insertar(2);
ArbolInt.Insertar(3);
ArbolInt.Insertar(4);
ArbolInt.Insertar(5);
ArbolInt.Insertar(6);
ArbolInt.Insertar(7);
ArbolInt.Insertar(8);
ArbolInt.Insertar(9);
ArbolInt.Insertar(10);
ArbolInt.Insertar(11);
ArbolInt.Insertar(12);
ArbolInt.Insertar(13);
ArbolInt.Insertar(14);
ArbolInt.Insertar(15);
ArbolInt.Insertar(16);

Pgina 53 de 91

cout << "Altura de arbol " << ArbolInt.AlturaArbol()


<< endl;
// Mostrar el rbol en tres ordenes distintos:
cout << "InOrden: ";
ArbolInt.InOrden(Mostrar);
cout << endl;
cout << "PreOrden: ";
ArbolInt.PreOrden(Mostrar);
cout << endl;
cout << "PostOrden: ";
ArbolInt.PostOrden(Mostrar);
cout << endl;
ArbolInt.Borrar(8);
ArbolInt.Borrar(11);
cout << "Altura de arbol " << ArbolInt.AlturaArbol()
<< endl;
// Mostrar el rbol en tres ordenes distintos:
cout << "InOrden: ";
ArbolInt.InOrden(Mostrar);
cout << endl;
cout << "PreOrden: ";
ArbolInt.PreOrden(Mostrar);
cout << endl;
cout << "PostOrden: ";
ArbolInt.PostOrden(Mostrar);
cout << endl;
/*

// Borraremos algunos elementos:


cout << "N nodos: " << ArbolInt.NumeroNodos() << endl;
ArbolInt.Borrar(5);
cout << "Borrar
5: ";
ArbolInt.InOrden(Mostrar);
cout << endl;
ArbolInt.Borrar(8);
cout << "Borrar
8: ";
ArbolInt.InOrden(Mostrar);
cout << endl;
ArbolInt.Borrar(15);
cout << "Borrar 15: ";
ArbolInt.InOrden(Mostrar);
cout << endl;
ArbolInt.Borrar(245);
cout << "Borrar 245: ";
ArbolInt.InOrden(Mostrar);
cout << endl;
ArbolInt.Borrar(4);
cout << "Borrar
4: ";

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

ArbolInt.InOrden(Mostrar);
ArbolInt.Borrar(17);
cout << endl;
cout << "Borrar 17: ";
ArbolInt.InOrden(Mostrar);
cout << endl;
// Veamos algunos parmetros
cout << "N nodos: " << ArbolInt.NumeroNodos() << endl;
cout << "Altura de 1 " << ArbolInt.Altura(1) << endl;
cout << "Altura de 10 " << ArbolInt.Altura(10) <<
endl;
cout << "Altura de arbol " << ArbolInt.AlturaArbol()
<< endl;
cin.get();
// Arbol de cadenas:
AVL<Cadena> ArbolCad;
// Insercin de valores:
ArbolCad.Insertar("Hola");
ArbolCad.Insertar(",");
ArbolCad.Insertar("somos");
ArbolCad.Insertar("buenos");
ArbolCad.Insertar("programadores");
// Mostrar en diferentes ordenes:
cout << "InOrden: ";
ArbolCad.InOrden(Mostrar);
cout << endl;
cout << "PreOrden: ";
ArbolCad.PreOrden(Mostrar);
cout << endl;
cout << "PostOrden: ";
ArbolCad.PostOrden(Mostrar);
cout << endl;
// Borrar "buenos":
ArbolCad.Borrar("buenos");
cout << "Borrar 'buenos': ";
ArbolCad.InOrden(Mostrar);
cout << endl; */
cin.get();
return 0;
}

Pgina 55 de 91

Implementacin en Java
/*
* Nombre: Arbol_AVL.java
* Descripcin: implementacin de la clase Arbol AVL
* Autor: Mark Allen Weiss ("Estructuras de datos en
Java")
*/
public class Nodo_AVL{
// Atributos
public Comparable info; // dato
public Nodo_AVL hijo_izq; // hijo izquierdo
public Nodo_AVL hijo_der; // hijo derecho
public int altura; // altura del nodo
// Constructores
Nodo_AVL( Comparable dato)
{ this( dato, null, null ); }
Nodo_AVL( Comparable dato, Nodo_AVL izq, Nodo_AVL der ){
info = dato;
hijo_izq = izq;
hijo_der = der;
altura = 0;
}
}
/*
* Nombre: Arbol_AVL.java
* Descripcin: implementacin de la clase Arbol AVL
* Autor: Mark Allen Weiss ("Estructuras de datos en
Java")
*
*/
public class Arbol_AVL{
private Nodo_AVL raiz;
// Constructor
public Arbol_AVL()
{ raiz = null; }
public Comparable buscar_Menor( )
{ return dato_Nodo( buscar_Menor( raiz ) ); }
public Comparable buscar_Mayor( )
{ return dato_Nodo( buscar_Mayor( raiz ) ); }
public Comparable buscar( Comparable x )
{ return dato_Nodo( buscar( x, raiz ) ); }
public void imprimir_arbol( )
{
if( arbol_esVacio( ) )
System.out.println( "ARBOL VACIO !!!" );
else
inorden( raiz );
}
protected void inorden(Nodo_AVL r) // recorrido del rbol
{

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

if (r != null){
inorden(r.hijo_izq);
System.out.print(r.info + " ");
inorden(r.hijo_der);
}
}
private Comparable dato_Nodo( Nodo_AVL t )
{ return t == null ? null : t.info; }
public void insertar( Comparable x )
{ raiz = insertar( x, raiz ); }
private Nodo_AVL insertar( Comparable x, Nodo_AVL t ){
if( t == null )
t = new Nodo_AVL( x, null, null );
else if( x.compareTo( t.info ) < 0 ){
// insertar por el subarbol izquierdo
t.hijo_izq = insertar( x, t.hijo_izq );
// verificar la altura del subarbol
if( altura( t.hijo_izq ) - altura( t.hijo_der ) == 2 )
if( x.compareTo( t.hijo_izq.info ) < 0 )
t = rotacion_derecha( t ); // rotacion simple
else
//rotacin compuesta
t = rotacion_compuesta_derecha( t );
}
else if( x.compareTo( t.info ) > 0 ){
// insertar por el subarbol derecho
t.hijo_der = insertar( x, t.hijo_der );
// verificar la altura del subarbol
if( altura( t.hijo_der ) - altura( t.hijo_izq ) == 2 )
if( x.compareTo( t.hijo_der.info ) > 0 )
t = rotacion_izquierda( t ); // rotacion simple
else
// rotacin compuesta
t = rotacion_compuesta_izquierda( t ); }
else
; // dato duplicado --> no se inserta
t.altura = max( altura( t.hijo_izq ), altura( t.hijo_der
) ) + 1;
return t;}
private Nodo_AVL buscar_Menor( Nodo_AVL t ){
if( t == null )
return t;
while( t.hijo_izq != null )
t = t.hijo_izq;
return t;
}
private Nodo_AVL buscar_Mayor( Nodo_AVL t ){
if( t == null )
return t;
while( t.hijo_der != null )

Pgina 57 de 91

t = t.hijo_der;
return t;
}
private Nodo_AVL buscar( Comparable x, Nodo_AVL t ){
while( t != null )
if( x.compareTo( t.info ) < 0 )
t = t.hijo_izq;
else if( x.compareTo( t.info ) > 0 )
t = t.hijo_der;
else
return t; // hallado
return null; // No hallado
}
// Retorna la altura del nodo t
private static int altura( Nodo_AVL t )
{ return t == null ? -1 : t.altura; }
private static int max( int lhs, int rhs ) // altura
mayor
{ return lhs > rhs ? lhs : rhs; }
// rotacin simple --> derecha, actualizacin de la
altura
private static Nodo_AVL rotacion_derecha( Nodo_AVL k2 ){
Nodo_AVL k1 = k2.hijo_izq;
k2.hijo_izq = k1.hijo_der;
k1.hijo_der = k2;
k2.altura = max(altura(k2.hijo_izq),altura(k2.hijo_der
))+1;
k1.altura = max( altura( k1.hijo_izq ), k2.altura ) + 1;
return k1;
}
// rotacion simple --> izquierda, actualizacion de la
altura
private static Nodo_AVL rotacion_izquierda( Nodo_AVL k1
){
Nodo_AVL k2 = k1.hijo_der;
k1.hijo_der = k2.hijo_izq;
k2.hijo_izq = k1;
k1.altura = max(altura(k1.hijo_izq), altura(k1.hijo_der
)) + 1;
k2.altura = max( altura( k2.hijo_der ), k1.altura ) + 1;
return k2;}
// rotacin compuesta a la derecha y actualizacin de la
altura
private static Nodo_AVL rotacion_compuesta_derecha(
Nodo_AVL k3 )
{
k3.hijo_izq = rotacion_izquierda( k3.hijo_izq );
return rotacion_derecha( k3 );
}

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

// rotacin compuesta a la izquierda y actualizacin de


la altura
private static Nodo_AVL
rotacion_compuesta_izquierda(Nodo_AVL k1)
{
k1.hijo_der = rotacion_derecha( k1.hijo_der );
return rotacion_izquierda( k1 );
}
public void arbol_Vacio( )
{ raiz = null; }
public boolean arbol_esVacio( )
{ return raiz == null; }
} // fin de clase
/*
Descripcin : Programa para probar la implementacin de la
clase
*/
import java.io.*;
public class Ejemplo_Arbol_AVL{
public static void main( String [] args ){
Arbol_AVL t = new Arbol_AVL( );
int n = 10;
String dato;
int vb = 0, aux;
InputStreamReader fe = new InputStreamReader(System.in);
BufferedReader buf = new BufferedReader(fe);
try{
do{
System.out.print("DIGITE UN DATO (PARA TERMINAR DIGITE 0):
");
dato = buf.readLine();
aux = Integer.parseInt(dato);
if (dato.compareTo("0") != 0)
t.insertar(new Integer(aux));
}while(dato.compareTo("0") != 0);
if (!t.arbol_esVacio())
System.out.print( "\nRecorrido del Arbol en Inorden: \n");
t.imprimir_arbol( );
if (!t.arbol_esVacio()){
System.out.print( "\nDigite el dato a buscar: ");
dato = buf.readLine();
vb = Integer.parseInt(dato);
if ( t.buscar(new Integer(vb)) == null)
System.out.println( "Dato NO hallado !" );
else{
System.out.println( "Dato hallado !" );
}
}
}catch(IOException e)
{ System.out.println ("Error : " + e.getMessage());}
} // fin del mtodo main
} // fin de la clase

Pgina 59 de 91

rboles N-arios
Se trata de una generalizacin de los rboles binarios. En este tipo de
estructura, se pueden manejar mltiples subrboles asociados a cada nodo y
no solamente dos como en el caso de los rboles Binarios (adems, un nodo
puede contener mltiples llaves -claves).
Formalmente, se define un rbol N-ario como una estructura jerrquica, en la
cual, cada nodo tiene un nmero cualesquiera de subrboles n-arios
asociados y hasta un mximo de n.

Los rboles N-arios, tienen su aplicacin particular en el modelado de


jerarquas con relacin de uno a muchos, y en el proceso de almacenamiento
externo de datos (en memoria secundaria discos duros, etc).
Nota: el termino llave clave, se utiliza sobretodo cuando se habla de
ordenamiento y en general es un dato (campo), que identifica de manera
nica a un registro (conjunto de datos).
rboles Multivas (Multiway)
Los rboles Multivas (Multiway, en ingls) son rboles N-arios que se
caracterizan por que cada nodo puede guardar ms de una llave (clave).
Estos rboles, surgen ante la necesidad de tener alternativas para
almacenamiento externo (memoria secundaria) de datos, donde el
desempeo se ve afectado por el nmero de veces que se accede al disco
duro.
Se define un rbol Multivas de orden N (N-vas), como un rbol N-ario,
donde si k es el nmero de hijos de un nodo, entonces:
El nodo contiene exactamente k-1 elementos o llaves.
Todo nodo del rbol contiene exactamente k-vas (k <= N)
Existe un concepto importante, y es el de rbol Multivas Ordenado, el
cual se define como un rbol Multivas, en el que adems las llaves (claves)
estn ordenadas.
As como un rbol Multivas es una generalizacin de los rboles Binarios, un
rbol
Multivas ordenado es una generalizacin de los rboles Binarios de Bsqueda
(BST).

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

rboles B
Un rbol B (Balanced - balanceado, equilibrado), es un caso particular de los
rboles Multivas. Una de sus caractersticas fundamentales, es que se trata
de mantener el rbol balanceado y garantizar un numero mnimo de claves
en cada nodo, exceptuando el nodo raz.
Los rboles B fueron introducidos por R. Bayer y E. McCreight en 1972, con el
propsito de mejorar el tiempo de acceso a estructuras de datos
almacenadas en memoria externa.
Cuando se almacena la estructura del rbol en memoria secundaria
(dispositivo de acceso lento: disco duro), y el acceder a un nodo, implica
acceder a un sector distinto del disco.
Entonces, se hace coincidir un sector fsico de la memoria, con el tamao de
un nodo, de manera que si un elemento ocupa e bytes, y un sector fsico
(disco) tiene un tamao f, en cada nodo se almacenarn f / e elementos.
De esta forma, se puede reducir notablemente el tiempo de acceso al disco
duro.
Los rboles B tienen las siguientes propiedades:
Los nodos terminales (hojas), tienen la misma altura.
Las claves de cada nodo deben estar ordenadas (ascendentemente).
No se permiten claves repetidas.
El orden, se determina con base al nmero de claves por nodo.
Si un nodo tiene N-claves, el nmero de subrboles que se pueden
desprender de l, es N+1, ninguno si es nodo terminal (hoja).
Un rbol es de orden N, cuando el numero mximo de subrboles
que se desprende de cualquier nodo es N+1, y el nmero mnimo de
subrboles no vacos es N + , exceptuando el nodo raz.
Cada nodo de un rbol B, esta conformado por variables de referencia
(apuntadores), las claves (llaves), y los datos (valores). Los componentes
dentro de cada nodo, estn ubicados de manera alterna. Usando las variables
de referencia, se enlaza con los nodos del siguiente nivel del rbol.

Pgina 61 de 91

Aplicaciones
Los rboles AVL (balanceados en altura), son muy buenos como estructuras
de datos en memoria primaria (RAM), pero muy deficientes para archivos, ya
que estos, requieren muchos accesos: por ser rboles binarios, son bastante
profundos.
Los rboles B surgieron (1972 - R.Bayer y E.McCreight) ante la necesidad de
mantener ndices en almacenamiento externo para acceder a las bases de
datos, es decir, con el grave problema de la lentitud de los discos duros, se
trat de aprovechar la capacidad de almacenamiento, para mantener una
gran cantidad de informacin, organizada de forma que el acceso a una clave
sea lo ms rpido posible.
En resumen, los rboles con mltiples hijos hacen que el mantenimiento de
ndices en memoria externa sea mucho ms eficiente y es justamente ste el
motivo por el que este tipo de rboles han sido los que tradicionalmente se
han usado para el mantenimiento de
ndices en sistemas de bases de datos.
rboles B
Una pgina es el elemento primario de la estructura y grficamente se podra
visualizar as:

48 50 60 70

M es el nmero mximo de llaves


M1 es el nmero mximo de apuntadores (M+1)
N=M/2 es el orden de un rbol B

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

rboles Rojinegro
Un rbol rojinegro es un rbol de bsqueda binaria con un bit extra de
almacenamiento por nodo: su color, el cual puede ser rojo o negro.
Los rboles rojinegros son estructuras basadas en rboles binarios
balanceados.
Un rbol rojinegro es un rbol de bsqueda binaria que satisface las
siguientes propiedades:
Cada nodo o es rojo o es negro
Cada hoja (nil) es negra
Si un nodo es rojo, entonces, sus hijos son negros
Cada camino de un nodo a cualquier descendiente tiene la misma
cantidad de nodos negros
Un rbol de bsqueda binaria es rojinegro si satisface las siguientes
propiedades:
1. Todo nodo es rojo o negro.
2. Toda hoja (nil) es negra.
3. La raz es negra.
4. Si un nodo es rojo, entonces sus hijos son negros.
5. Cada ruta simple de un nodo a una hoja descendiente contiene el
mismo nmero de nodos negros.
Estas propiedades hacen que un rbol rojinegro sea balanceado.

Pgina 63 de 91

La altura negra de un nodo x, an(x), es el nmero de nodos negros que hay


en cualquier camino de l a una hoja que desciende de l.
La altura negra de un rbol es la altura negra de su raz.
Sea A un rbol rojinegro con n nodos internos
Si x es un nodo en A, entonces, el subrbol con raz en x tiene a al
menos 2an(x)-1 nodos internos.
Sea x un nodo en A, por induccin sobre an(x)
A) Si an(x) = 0, entonces, x es hoja y no hay nodos en el subrbol con
raz en l.
Por otro lado, 2an(x)-1 = 0.
B) Supongamos que an(x) > 0, x es interno y tiene dos hijos. Es
inmediato que cualquier hijo y de x cumple con lo siguiente:
o C(y) = rojo, entonces, an(y) = an(x)
o C(y) = negro, entonces, an(y) = an(x) 1
Por hiptesis de induccin, el nmero de nodos descendientes de x es al
menos:
Nodescendientes(dere(x))+1+No_descendientes(izq(x))=1+2(2an(x)-1-1)=2an(x)-1
La altura de A es a lo sumo 2log2(n +1).
Sea h la altura del rbol rojinegro.
o Al menos la mitad de los nodos en un camino de la raz a una hoja,
sin incluir la raz, deben ser negros.
o La altura negra del rbol debe ser al menos h/2
o Por lo anterior,
o n = 2 h/2-1 Y log2(n +1) = h/2 Y h = log2(n +1)
Los rboles rojinegros son rboles de bsqueda binaria en donde las
hojas tienen valores nulos.
Los algoritmos para rboles de bsqueda binaria se aplican a los
rboles
rojinegros.
Al insertar una nueva llave quedar como padre de dos hojas nulas.
La operacin de bsqueda toma un tiempo O(log n) en el peor caso.
Las operaciones de Insercin y Supresin son tambin O(log n) pero no
necesariamente mantienen estructuras rojinegras.

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

Rotaciones
Las operaciones Tree-Insert y Tree-Delete toman un tiempo O(log n)
en un rbol rojinegro con n llaves.
El resultado de insertar o eliminar nodos en un rbol rojinegro usando
el algoritmo de rboles de bsqueda binaria, podra violar las
propiedades de los rboles rojinegros.
De modo que cuando se realizan las operaciones de insercin o
eliminacin, puede que se deba cambiar los colores de algunos de los
nodos y tambin cambiar el apuntador al nodo.
El apuntador al nodo se cambia mediante una rotacin, la cual es una
operacin local que preserva el ordenamiento de las llaves.
La siguiente figura muestra los dos tipos de rotaciones: rotacin a la
izquierda y a la derecha.

LeftRotate (Rotacin a la Izquierda)

El cdigo para la rotacin a la izquierda de un nodo x asume que:


right[x] NIL
LEFT-ROTATE (T,x)
1 y  right[x]
---> Asigna y
2 right[x]  left[y] ---> Convierte el subrbol izquierdo de y al subrbol
derecho de x
3 p[left[y]]  x
4 p[y]  p[x]
---> Enlaza el padre de x a y
5 if p[x] = Nil

Pgina 65 de 91

6
then root[T]  y
7
else if x = left[p[x]]
8
then left[p[x]]  y
9
else right[p[x]]  y
10 left[y]  x
---> Pone x a la izquierda de y
11 p[x]  y
La siguiente figura muestra como opera Left-Rotate.

La rotacin a la izquierda pivotea alrededor del enlace de x a y.


Esto hace que y sea la nueva raz del subrbol, con x como el hijo
izquierdo de y y el hijo izquierdo de y como el hijo derecho de x.
El cdigo para RIGHT-ROTATE es similar.
Ambos procedimientos corren en un tiempo O(1), ya que slo los
apuntadores cambian en una rotacin.

RightRotate (Rotacin a la Derecha)

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

Recorridos
Recorrido EntreOrden
RecorridoEntreOrden( x )
begin
if x <> nil then begin
RecorridoEntreOrden( left[x] );
writeln( x );
RecorridoEntreOrden( right[x] )
end
end;

Recorrido PreOrden
RecorridoPreOrden( x )
begin
if x <> nil then begin
writeln( x );
RecorridoPreOrden( left[x] );
RecorridoPreOrden( right[x] )
end
end;
Recorrido PosOrden
RecorridoPosOrden( x )
begin
if x <> nil then begin
RecorridoPosOrden( left[x] );
RecorridoPosOrden( right[x] )
writeln( x );
end
end;

Recorrido EntreOrden
Las rotaciones izquierda y derecha preservan entrerdenes. Esto es, si A es el
recorrido entreorden, x est antes que y en A y B es el recorrido entreorden
despus de aplicar una rotacin en x, entonces, x est antes que y en B.
En efecto, consideremos situacin derecha de la figura y una rotacin
izquierda sobre y.
Se tiene = x = = y = .
Despus de aplicar la rotacin a la izquierda el orden se preserva.

Pgina 67 de 91

Insercin
Al insertar nuevos elementos en rboles rojinegros, en tiempo O(log
n), se debe garantizar que el rbol resultante contine siendo
rojinegro
En los rboles rojinegros las hojas son vacas y negras
Los nuevos elementos se colocan como padres de hojas
Cada nuevo elemento se coloca como una estructura del rbol binario
Como las hojas deben ser negras, el nodo que contiene la llave a
insertarse se colorea como rojo

No se aumenta la altura negra del rbol


La nica propiedad que puede violarse es la referente al color del
padre del nodo que se ha insertado
RB-Insert(T,z)
1 y nil
2 x root[T]
3

while x nil

do y  x

if key[z] < key[x]

then x left[x]

else x  right[x]

8 p[z]  y
9 if y = nil
10

then root[T]  z

11

else if key[z] < key[y]

12

then left[y]  z

13

else right[y]  z

14

right[z]  nil

15

left[z]  nil

16

color[z]  red

17

RB-INSERT-FIXUP(T,z)

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

RB-INSERT-FIXUP(T,z)
1
2

while color[p[z]] = RED


do if p[z] = left[p[p[z]]]

then y  right [p[p[z]]]

if color[y] = RED

then color[p[z]]  BLACK

---> Caso 1

color[y]  BLACK

---> Caso 1

color[p[p[z]]]  RED

---> Caso 1

z p[p[z]]

else if z = right[p[z]]

10

---> Caso 1

then z  p[z]

---> Caso 2

11

Left-Rotate(T,z)

---> Caso 2

12

color[p[z]]  BLACK

---> Caso 3

13

color[p[p[z]]]  RED

---> Caso 3

14

Right-Rotate(T,p[p[z]])

---> Caso 3

15

else (lo mismo que el then cambiando right por left y


viceversa)

16 color[root[T]]  BLACK

Eliminacin
Como las otras operaciones en los rboles rojinegros, la eliminacin de un
nodo toma un tiempo O(log n).
Coincide con la operacin de eliminacin en los rboles de bsqueda
binaria
Sin embargo, es necesario mantener la estructura de los rboles
rojinegros
Para evitar repeticiones se introduce centinela, nil(A), el cual representa
las hojas del rbol rojinegro
Si el nodo suprimido y fuese rojo, entonces, las alturas negras no cambian
y, en tal caso, termina

Pgina 69 de 91

Si el nodo suprimido y fuese negro, entonces, las ramas que pasen por y
tienen un nodo negro menos, lo que viola la condicin de los rboles
rojinegros. En este caso es necesario ajustar colores.
El procedimiento RB-DELETE es una modificacin de TREE-DELETE, con tres
diferencias:
1. Todas las referencias a nil han sido reemplazadas por referencias al
centinela NIL [T].
2. Debido a la ausencia de condiciones de lmites, la asignacin p[x] 
p[y] se realiza incondicionalmente.
3. Se hace un llamado al procedimiento RBDelete-Fixup

RB-DELETE(T,z)
1
if left[z] = nil[T] or right[z] = nil[T]
2

then y  z

else y TREE-SUCCESSOR(z)

if left[y] nil[T]

then x  left[y]

else x right[y]

p[x]  p[y]

if p[y] = nil[T]

then root[T]  x

10

else if y = left[p[y]]

11

then left[p[y]]  x

12

else right[p[y]]  x

13

if y z

14

then key[z]  key[y]

15

--->Si y tiene otros campos, se copian tambin.

16
17
18

if color[y] = BLACK
then RB-DELETE-FIXUP(T,x)
return y

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

RB-DELETE-FIXUP(T,x)
1
2

while x root[T] and color[x] = BLACK


do if x = left[p[x]]

then w  right[p[x]]

if color[w] = red

then color[w] BLACK

---> Caso 1

color[p[x]] RED

---> Caso 1

LEFT-ROTATE(T,p[x])

---> Caso 1

w right[p[x]] B Caso 1

if color[left[w]] = BLACK and color[right[w]] = BLACK

10

then color[w]  RED

11

x  p[x]

---> Caso 2
---> Caso 2

12

else if color[right[w]] = BLACK

13

then color[left[w]]  BLACK

---> Caso 3

14

color[w]  RED

---> Caso 3

15

RIGHT-ROTATE(T,w)

---> Caso 3

16

w  right[p[x]]

---> Caso 3

17

color[w]  color[p[x]]

---> Caso 4

18

color[p[x]]  BLACK

---> Caso 4

19

color[right[w]]  BLACK

---> Caso 4

20
21
22
23

LEFT-ROTATE(T,p[x])
x  root[T]
else (lo mismo que el then
cambiando right por left y viceversa)
color[x]  BLACK

---> Caso 4
---> Caso 4

Las operaciones de insercin y eliminacin recorren un rbol


rojinegro a lo ms dos veces.
Por tanto, su complejidad en tiempo para el peor caso est acotada
por O( log n )

Pgina 71 de 91

Implementacin en Java
import
import
import
import

javax.swing.*;
java.awt.*;
java.util.*;
java.awt.event.*;

public class RedBlack extends JPanel{


public static byte black = 0;
public static byte red = 1;
private NodoRb raiz;
boolean flag_esta; //booleano para indicar que la
operacion de insercion se puede hacer
boolean flag_esta2;//booleano para indicar que la
operacion de eliminacion se puede hacer
boolean step = true;
boolean run_pid = false;
//**Los nodos Padre Hijo Izquierdo, derecho y tio.
static NodoRb nodox = null;
static NodoRb nodoy = null;
static NodoRb nodoz = null;
static NodoRb nodow = null;
Child_window ventana_hija = new Child_window();
//Nuevo objeto que crea el receptor de resultados
public RedBlack(){raiz = null;} //funcion inline
contructor del Arbol Inicial
//funcion arbol vacio
public boolean IsEmpty(){
if (raiz == null)
return (true);
else
return(false);
}
/*
*Insertar en el arbol balanceado
*extraido desde *www.ica.org.ve/algoritmos *
*/
public void insertar_balanceado(NodoRb z)
{
NodoRb y = null;
NodoRb x = raiz;
while (x != null)
{
y = x;
//Comparamos si elem de z es menor a elem de x
if (z.elem.compareTo(x.elem) < 0)
x = x.izq;

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

else
x = x.der;
}//fin while
z.padre = y;
if (y == null)
raiz = z;
else
if (z.elem.compareTo(y.elem) < 0)
y.izq = z;
else
y.der = z;
z.izq = null;
z.der = null;
z.color = red;
}
//**Mtodo que entrega un booleano. Se usa para saber
si un elemento est o no en el arbol
private boolean estaEnArbol(NodoRb a,Comparable elem)
{
if (a == null)
return false;
else
if (elem.compareTo(a.elem) == 0)
return true;
else
return estaEnArbol(a.izq,elem) ||
estaEnArbol(a.der,elem);
}
//*Luego de la eliminacin de un nodo eliminamos los
centinelas ya que solo se ocupa para ello
private void eliminarCentinelas(NodoRb x)
{
if (x == null)
return;
if( x.FLAG )
{
if( x.padre.izq.FLAG )
x.padre.izq = null;
if( x.padre.der.FLAG )
x.padre.der = null;
}
else
{
eliminarCentinelas(x.izq);
eliminarCentinelas(x.der);

Pgina 73 de 91

}
}
public void insertarRB(Comparable elem)
{
flag_esta = false;
if (estaEnArbol(raiz,elem)) // si elem ya se
encuenra en el arbol, no se vuelv6 a insertar
{
JOptionPane.showMessageDialog(null,""+(elem)+" ya se
encuentra en el arbol Red-Black.","Atencin.",
JOptionPane.PLAIN_MESSAGE);
flag_esta = true;
return;
}
eliminarCentinelas(raiz);
NodoRb x = new NodoRb(elem); //Se crea un nuevo
nodo para insertarlo en el arbol red-black
insertar_balanceado(x);
//Insertamos el
nuevo nodo al arbol primeramente como en un arbol ABB
while (x != raiz && x.padre.color == red)
//mientras el arbol no cumpla con las condiciones de RBtree
{
boolean nodo_Y_rojo = false;
//
variable booleana que almacena true si y es rojo y falso
si el nodo Y es negro
if (x.padre == x.padre.padre.izq) // si el
padre de x es igual al abuelo de x que apunta al hijo
izq.
{
NodoRb y = x.padre.padre.der;
if (y != null)
{
if (y.color == red)
{
//Recolorar para el caso 1 de insercin
x.padre.color = black;
y.color = black;
x.padre.padre.color = red;
x = x.padre.padre;
nodo_Y_rojo = true;
}
}
if ( !nodo_Y_rojo)
{
if (x == x.padre.der )
{
// caso 2: realizar una rotacion a la izq sobre x
x = x.padre;

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

rotarLeft(x);
}
// caso 3: Realizar rotacion
//a la derecha sobre el padre del padre de x
x.padre.color = black;
x.padre.padre.color = red;
rotarRight(x.padre.padre);
}
}
else
{
if (x.padre == x.padre.padre.der ) // si
el padre de x es igual al abuelo de x que apunta al hijo
der.
{
NodoRb y = x.padre.padre.izq; // aplicamos
los casos para esta situacion
if (y != null)
{
if (y.color == red)
{
//Recolorar para el caso 1 de insercin
x.padre.color = black;
y.color = black;
x.padre.padre.color = red;
x = x.padre.padre;
nodo_Y_rojo = true;
}
}
if (! nodo_Y_rojo)
{
// caso 2: Realizamos una rotacion a la derecha sobre el
nodo x
if (x == x.padre.izq)
{
x = x.padre;
rotarRight(x);
}
// caso 3: Realizamos una rotacion a la izquierda sobre
el abuelo de x
x.padre.color = black;
x.padre.padre.color = red;
rotarLeft(x.padre.padre);
}
}

Pgina 75 de 91

}
}
raiz.color = black;
arbol es negra
crearCentinela(raiz);
}

// siempre la raiz del

//**Mtodo para eliminar un nodo de un arbol red-black


public void eliminarRB(Comparable elem)
{
flag_esta2 = true;
if( IsEmpty() ) // si Arbol esta vacio, se avisa
al usuario
{
JOptionPane.showMessageDialog(this,"Arbol
Red-Black vacio.","Arbol
Vacio.",JOptionPane.PLAIN_MESSAGE);
flag_esta2 = false;
return;
}
NodoRb z = buscarNodo(raiz,elem);
if( z == null )// si el dato no se encuentra se
avisa al usuario.
{
JOptionPane.showMessageDialog(this,"El
elemento a eliminar no se encuentra en el Arbol RedBlack.",
"Arbol Red-Black.",JOptionPane.OK_OPTION);
flag_esta2 = false;
return;
}
// Trasferido el valor se procede a asignar el nodo p
como elemento a eliminar
NodoRb p = eliminarRB(z);
p = null; //eliminamos definitivamente el nodo p
ya se ha traspazado
if( raiz.FLAG ) // si la raiz es centinela,
{
//Se procede a eliminar
raiz.padre = null;
raiz = null;
}
eliminarCentinelas(raiz); //No necesitamos los
centinelas
crearCentinela(raiz);
}

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

//**Retorna el nodo menor


private NodoRb nodoMin(NodoRb x)
{
while (!x.izq.FLAG)
x = x.izq;
return x;
}
//**Retorna el nodo sucesor del nodo X
private NodoRb Sucesor(NodoRb x)
{
if( !x.der.FLAG )
return nodoMin(x.der);
NodoRb y = x.padre;
while( y != null && x == y.der )
{
x = y;
y = y.padre;
}
return y;
}
//Mtodo elimina los nodos indicados del arbol redblack
private NodoRb eliminarRB(NodoRb z)
{
nodoz = z;
NodoRb y; NodoRb x;
String Caso_Y ="";
String Caso_X ="";
if (z.izq.FLAG || z.der.FLAG)//si algun hijo de z
es centinela
{
y = z;
Caso_Y = "Como el nodo Z posee uno o ningun
hijo, entonces, el nodo Y es igual al nodo Z";
}
else
{
y = Sucesor(z);
Caso_Y = "Como el nodoZ posee ambos hijos,
entonces, el nodo Y queda representado como \nel sucesor
de Z";
}
nodoy = y;

Pgina 77 de 91

if( !y.izq.FLAG )//si hijo izquierdo de y es el


centinela
{
x = y.izq;
Caso_X = "Como el hijo izq. del nodo Y no es
centinela, entonces, este sera el nodo Y";
}
else
{
x = y.der;
Caso_X ="Como el hijo izq. del nodo Y es
centinela, entonces, el nodo X es el hijo der. de Y";
}
nodox = x;
repaint();
ventana_hija.texto.append("* El nodo Z es el
elemento que deseas eliminar\n (Z = "+ z.elem +
")\n"+ Caso_Y +"(Y = "+ y.elem + ")\n "+
Caso_X +"(X = arbitrario).");
paso_a_paso();
String mensaje = "El padre de X es ahora el nodo
Z";
repaint(); // Es repintado el dibujo del arbol
x.padre = y.padre;
if (y.padre == null) // si padre de y es nulo
{
raiz = x;
mensaje+= "\nComo el nodo Y no tiene padre,
entonces, el nodo X es ahora la raiz del arbol";
}
else
{
if( y == y.padre.izq )
{
y.padre.izq = x;
mensaje += "\nAhora el nodo X pasa a ser
el hijo izq. de Z";
}
else
{
mensaje += "\n Ahora el nodo X es el hijo
der. de Z";
y.padre.der = x;
}
}
nodox = x;
if( y != z )
{

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

z.elem = y.elem;
mensaje += "\nComo el nodo Z es igual al nodo
Y, ahora la llave del nodo Z\n es igual a la llave del
nodo Y";
repaint(); // Es repintado el dibujo del
arbol
}
if( y.color == black )
{
mensaje += "\nEl color del nodo Y es black,
entonces. se llama al metodo para rebalancear el
arbol.\n"+
"Rebalancear arbol : Es el que se
encarga de devolver las propiedades red-black al arbol";
ventana_hija.texto.append(mensaje +"\n");
paso_a_paso();
repaint(); // Es repintado el dibujo del arbol
Corregir_red_black(x);//Corregir el posible
desbalanceo
}
else
{
ventana_hija.texto.append(mensaje +"\n");
paso_a_paso();
repaint(); // Es repintado el dibujo del
arbol
}
// se asigna null a las variables auxiliares
nodox = null;nodoy = null;nodoz = null;nodow =
null;
return y;// retorno el nodo ha eliminar
}
//**Mtodo de rotacin a la izquierda
//http://cuaima.ica.luz.ve/algoritmos/guiarojonegros.
pdf
private void rotarLeft(NodoRb x)
{
NodoRb y = x.der;
x.der = y.izq;
if( y.izq != null )
y.izq.padre = x;
y.padre = x.padre;
if( x.padre == null )
raiz = y;
else
if( x == x.padre.izq )
x.padre.izq = y;
else
x.padre.der = y;

Pgina 79 de 91

y.izq = x;
x.padre = y;
}
//**Mtodo de rotacin a la izquierda
private void rotarRight(NodoRb x)
{
NodoRb y = x.izq;
x.izq = y.der;
if( y.der != null )
y.der.padre = x;
y.padre = x.padre;
if( x.padre == null )
raiz = y;
else
if( x == x.padre.der )
x.padre.der = y;
else
x.padre.izq = y;
y.der = x;
x.padre = y;
}
//**Mtodo para Pintar los Nodos
public void paintChildren(Graphics g)
{
g.setFont(new Font("small",5,10) );
dibujo(g,raiz, 130, 10, 7.5, 0);
}
//Creacion de los centinelas para su uso en la
eliminacin
private void crearCentinela(NodoRb x)
{
if( x.izq == null ){
NodoRb centinela = new NodoRb(x);
x.izq = centinela;
}
else
{
crearCentinela(x.izq);
}
if( x.der == null )
{
NodoRb centinela = new NodoRb(x);
x.der = centinela;
}
else
{
crearCentinela(x.der);
}

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

}
//**Mtodo para el corregimiento del arbol. Al insertar o
eliminar nodos pudo haberse violado una o ms condiciones
del red-ba
private void Corregir_red_black(NodoRb x)
{
nodoz = nodoy = null;
while( x != raiz && x.color == black )// mientras
el arbol no sea red black
{
nodox=x;
if (x == x.padre.izq ) // Si x esta a la izq.
de su padre, entonces aplicamos 4 casos para Hijo
izquierdo
{
NodoRb w = x.padre.der;
nodow = w;
repaint();
ventana_hija.texto.append(" * Como el
nodo x representa al hijo izq, entonces, el nodo W
representa al hijo derecho\n");
/** Caso 1 **/
if (w.color == red)
{
ventana_hija.texto.append("* CASO 1:
Nodo W es Rojo\n");
paso_a_paso();
repaint();
ventana_hija.texto.append("---> 1) El
color del nodo W cambia a Negro\n");
paso_a_paso();
w.color = black;
// caso 1
repaint();
ventana_hija.texto.append("---> 2) El
color del padre del nodo X cambia a Rojo\n");
paso_a_paso();
repaint();
x.padre.color = red; // caso 1
ventana_hija.texto.append("---> 3) Se
realiza una rotacion a la izquierda sobre el padre del
nodo X\n");
paso_a_paso();
rotarLeft(x.padre);
// caso 1
repaint();
ventana_hija.texto.append("---> 4) El
nodo W pasa a ser el hijo der.del padre del nodo X\n");
paso_a_paso();

Pgina 81 de 91

w = x.padre.der;
// caso 1
repaint();
ventana_hija.texto.append("* FIN DEL
CASO 1\n");
}
/** Caso 2 **/
if (w.izq.color == black && w.der.color
== black )
{
ventana_hija.texto.append("CASO 2: El
color de los hijos del nodo W son Negros\n");
paso_a_paso();
ventana_hija.texto.append("---> 2) El
color del nodo W cambia a Rojo.\n");
paso_a_paso();
w.color = red;
// caso 2
repaint();
ventana_hija.texto.append("---> 2) El
nodo X pasa a ser el padre\n");
paso_a_paso();
x = x.padre;
// caso 2
repaint();
}
else
{
/** Caso 3 **/

3: El
1) El

2) El

3) Se
W\n");

if( w.der.color == black )


{
ventana_hija.texto.append("* CASO
color del hijo derecho. de W es Negro\n");
ventana_hija.texto.append("--->
color del hijo izquierdo. de W cambia a Negro\n");
paso_a_paso();
w.izq.color = black; // caso 3
repaint();
ventana_hija.texto.append("--->
color de W cambia a Rojo\n");
paso_a_paso();
w.color = red;
// caso 3
repaint();
ventana_hija.texto.append("--->
realiza una rotacion a la derecha sobre el nodo

paso_a_paso();
rotarRight(w);
// caso 3
repaint();
ventana_hija.texto.append("--->
4) El nodo W es ahora el hermano derecho del nodo X\n");

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

paso_a_paso();
w = x.padre.der;
nodow = w;
repaint();

// caso 3

}
/** Caso 4 **/
ventana_hija.texto.append("CASO
4: El nodo W es Negro y su hijo derecho. es Rojo\n");
paso_a_paso();
ventana_hija.texto.append("--->
1) El color del nodo W es ahora el color del padre del
nodo X\n");
paso_a_paso();
w.color = x.padre.color; // caso
4
repaint();
ventana_hija.texto.append("--->
2) El color del padre del nodo X es ahora negro\n");
paso_a_paso();
x.padre.color = black;
// caso
4
repaint();
ventana_hija.texto.append("--->
3) El color del hijo derecho de W cambia a Negro.\n");
paso_a_paso();
w.der.color = black;
// caso
4
repaint();
rotarLeft(x.padre);
// caso
4
ventana_hija.texto.append("--->
4) Se realiza una rotacion a izquierda al padre del nodo
X.\n");
paso_a_paso();
repaint();
ventana_hija.texto.append("--->
5) La raiz del arbol es rotulado como X\n");
paso_a_paso();
x = raiz;
// caso
4
nodox = x;
repaint();
ventana_hija.texto.append("--->
4) Finalmente el arbol se encuentra balanceado\n");
}
}
else

Pgina 83 de 91

{
if( x == x.padre.der )
// Si x esta
a la der. de su padre, entonces aplicamos 4 casos para
Hijo derecho
{
NodoRb w = x.padre.izq;
nodow = w;
repaint();
ventana_hija.texto.append("* Como
el nodo X representa al hijo derecho, entonces, el nodo W
representa al hijo izquierdo\n");
/** Caso 1 **/
if ( w.color == red )
{
ventana_hija.texto.append("*
CASO 1: El en nodo a eliminar W es Rojo\n");
paso_a_paso();
repaint();
ventana_hija.texto.append("--> 1) El color del nodo W cambia a negro\n");
paso_a_paso();
w.color = black;
// caso
1
repaint();
ventana_hija.texto.append("--> 2) El color del padre del nodo X cambia a rojo\n");
paso_a_paso();
x.padre.color = red;// caso 1
repaint();
ventana_hija.texto.append("--> 3) Se realiza una rotacion a la derecha sobre el padre
del nodo X\n");
paso_a_paso();
rotarRight(x.padre); // caso
1
repaint();
ventana_hija.texto.append("--> 4) El nodo W pasa a ser el hijo izquierdo del padre
del nodo X\n");
w = x.padre.izq;
// caso
1
repaint();
}
/** Caso 2 **/

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

if( w.der.color == black &&


w.izq.color == black )
{
ventana_hija.texto.append("Caso 2: El color de los
hijos del nodo W son negros\n");
ventana_hija.texto.append("--> 1) El color del nodo W cambia a rojo\n");
paso_a_paso();
w.color = red;
// caso 2
repaint();
ventana_hija.texto.append("--> 2) El nodo X pasa a ser su mismo padre\n");
ventana_hija.texto.append("****FIN CASO 2\n");
x = x.padre;
// caso
2
repaint();
}
else
{
/** Caso 3 **/
if( w.izq.color == black )
{
ventana_hija.texto.append("*
CASO 3: El color del hijo izquierdo. de W es negro \n");
ventana_hija.texto.append("--> 1) El color del hijo derecho. de W cambia a negro\n");
paso_a_paso();
w.der.color = black; // caso
3
repaint();
ventana_hija.texto.append("--> 2) El color del nodo W cambia a rojo\n");
paso_a_paso();
w.color = red;
// caso 3
repaint();
ventana_hija.texto.append("--> 3) Se realiza una rotacion a la izquierda sobre el
nodo W\n");
paso_a_paso();
rotarLeft(w);
// caso
3
repaint();

Pgina 85 de 91

ventana_hija.texto.append("--> 4) El nodo W es ahora el hermano izquierdo del nodo


X\n");
paso_a_paso();
w = x.padre.izq;
// caso
3
nodow = w;
repaint();
}
/** Caso 4 **/
ventana_hija.texto.append("*
CASO 4: El nodo W es Negro y su hijo izquierdo es
rojo\n");
ventana_hija.texto.append("--> 1) El color del nodo W es ahora el color del padre del
nodo X\n");
paso_a_paso();
w.color = x.padre.color; //
caso 4
repaint();
ventana_hija.texto.append("--> 2) El color del padre del nodo X ahora es Negro\n");
paso_a_paso();
x.padre.color = black;
//
caso 4
repaint();
ventana_hija.texto.append("--> 3) El color del hijo izquierdo. de W cambia a
negro\n");
paso_a_paso();
w.izq.color = black;
//
caso 4
repaint();
ventana_hija.texto.append("--> 4) Se realiza una rotacion derecha al padre del nodo
X\n");
paso_a_paso();
rotarRight(x.padre);
//
caso 4
repaint();
ventana_hija.texto.append("--> 5) La raiz del arbol es rotulado como X\n");
paso_a_paso();
x = raiz;
//
caso 4
nodox=x;

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

repaint();
ventana_hija.texto.append("--> 6) Arbol Con balanceado Corregido....\n");
}
}
}
}// fin while
ventana_hija.texto.append("FINALIZADO EL
PROCESO DE REBALANCEO....\n");
x.color = black;// el nodo x debe ser black
nodox=x;
repaint();
}
//**Necesitamos buscar el nodo a eliminar
private NodoRb buscarNodo(NodoRb x , Comparable elem)
{
while( x != null && elem.compareTo(x.elem) != 0
)
if (elem.compareTo(x.elem) < 0 )
x = x.izq;
else
x = x.der;
return x;
}
//**Eliminamos el arbol
public void Limpiar()
{
Limpiar(raiz);
raiz = null;
repaint();
}
//**Para cada nodo se eliminan sus referencias
private void Limpiar(NodoRb x)
{
if( x != null ){
Limpiar(x.izq);
Limpiar(x.der);
x = null;
}
}
private void dibujo(Graphics g,NodoRb cabeza, int a,
int b, double c, int d)
{

Pgina 87 de 91

if ( cabeza != null ) {
if( cabeza.color == 0 )
g.setColor(Color.black);
else
g.setColor(Color.red);
if (!cabeza.FLAG) {
g.fillOval( 240 + a , 35 + b , 28
un ovalo
g.setColor(Color.white); //color
de la informacion del nodo (el numero)
, 28 ); //dibuja nodo

/* Ubica la informacion en el centro


del nodo*/
String nod = ""+cabeza.elem;
int large = nod.length();
if (large==1){
g.drawString(nod,252 + a, 53 + b);
//escribe el numero en el nodo
}
else if(large==2)
g.drawString(nod,249 + a, 53 +
b);
else
if(large==3)
g.drawString(nod,244 +
a, 53 + b);
else
g.drawString(nod,240 +
a, 53 + b);
g.setColor(Color.black); //color de las ramas
del arbol
}
else /* se dibujan los centinelas*/
{
g.fillRect( 245 + a , 35 + b , 23 , 20 );
g.setColor(Color.white);
g.drawString("null", 248 + a, 46 + b);
g.setColor(Color.blue);
}
if (d == 1 ) // hijo izquierdo
g.drawLine(240 + a + (int)Math.pow( 2, c+1
), b - 20 , 258 + a,36 + b);
else if(d==2) // hijo derecho
g.drawLine(267 + a - (int)Math.pow( 2, c+1
), b - 22, 245 + a,36 + b);

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

g.setColor(Color.black);
dibujo(g,cabeza.izq,a - (int)Math.pow(2,c) (int)Math.pow(2,d-6), b + 75, c - 1 , 1 );//Recursivo
para el dibujo de cada rama
dibujo(g,cabeza.der,a + (int)Math.pow(2,c) +
(int)Math.pow(2,d-6), b + 75, c - 1 , 2 );
}
}// fin dibujo
//Esta clase Crea la ventana de los resultados, se
compone de un panelsscroll, un jtextarea, y 3 botones
//Los botones sirven para ejecutar paso a paso, limpiar
el texto y para ejecutar directamente
class Child_window extends JFrame{
public JTextArea texto;
public JPanel control;
Child_window(){
JFrame sub_ventana = new JFrame();
sub_ventana.setLocation(750,1);
texto = new JTextArea(37,16);
JButton wait = new JButton("Pasos", new
ImageIcon("./images/Play_button.gif"));
wait.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
step = true; run_pid = false;
}
});
JButton clear = new JButton("Limpiar", new
ImageIcon("./images/erase_icon.gif"));
JButton run = new JButton("Run", new
ImageIcon("./images/run.gif"));
run.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
run_pid = true; step = false;
}
});
clear.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
texto.setText("");
}
});
control = new JPanel();
control.add(wait);
control.add(clear);
control.add(run);
sub_ventana.getContentPane().add(control,BorderLayout.SOU
TH);

Pgina 89 de 91

JScrollPane pScroll = new JScrollPane(texto,


JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
sub_ventana.getContentPane().add(pScroll,BorderLayout.CEN
TER);
sub_ventana.setTitle("Resultados de las
Rotaciones");
sub_ventana.setVisible(true);
sub_ventana.pack();
sub_ventana.toFront();
}
}
//Esta ventana se muestra informando al usuario que esta
en modo insercin paso a paso. La ventana desaparece
// si el usuario presiona en el boton run
public void paso_a_paso(){
if (step == true && run_pid == false){
JOptionPane.showMessageDialog(ventana_hija.control,"Elimi
nacin paso a paso\n"+
"El programa Almacena los
resultados en una ventana de texto\n"+
"Si no desea ver este mensaje
presione en el icono del cd\n",
"Aviso de ejecucin paso a
paso",JOptionPane.ERROR_MESSAGE);
}
}
}

Recopilacin: Dary Nadyme Cardona Z.

rboles
Fundamentos de Anlisis y Diseo de Algoritmos

Bibliografa
Estructuras de Datos y Algoritmos, Alberto Jaime Sisa, Prentice Hall.
Estructuras de datos en C. Aarn M. Tanenbaum, Y. Langsam & M.
Augenstein, Prentice Hall.
Estructuras de Datos, Osvaldo Cair & Silvia Guardati, McGraw Hill.
Estructuras de Datos en Java. Mark Allen Weiss, Addison-Wesley.
Fundamentos de Programacin. Algoritmos y Estructuras de Datos. Luis
Joyanes Aguilar, McGraw Hill.
Data Structure & Algorithms. Aho, Hopcroff, Ullman. Addison Wesley.
Cmo Programar en Java. Deitel & Deitel, Prentice Hall.
Introduccin a los algoritmos, T.Cormen.
Matematicas discretas Y Combinatoria, Ralph Grimaldi
Discrete Mathematics, Rosen
Algoritmos computacionales, Baase y Van Gelder.

Referencias
Donald E. Knuth. The Art Of Computer Programming, Volume 1 /
Fundamental Algorithms. 2nd edition, Addison Wesley.
Aho, Hopcroff, Ullman. Data Structure & Algorithms. Addison Wesley. 1983
Alberto Jaime Sisa. Estructuras de Datos y Algoritmos. Prentice Hall.
Aarn M. Tanenbaum, Y. Langsam & M. Augenstein. Estructuras de datos en
C. Prentice Hall.
R. Graham, D. Knuth, O. Patashnik, Concrete Mathematics, 2nd edition,
Addison Wesley, 1994. -> El problema de Josephus
G.M. Adelson-Velskii, E.M. Landis. An Algorithm for the Organization of
Information Dokl. Akad. Nauk SSSE, Mathemat., 146:2, pp. 263-266. 1962.

Referencias en Internet
rboles
http://rinconprog.metropoliglobal.com/CursosProg/ProgGen/Estr_Datos/index
.php?cap=1
http://informatica.uv.es/iiguia/2000/AED/
http://www.indiana.edu/~call/ejercicios.html
http://www.lcc.uma.es/~galvez/ftps.html
http://cuaima.ica.luz.ve/algoritmos/guiarojonegros.pdf
http://ingecomp.mforos.com/users/darkspawn2004/

Estructuras de Datos
http://gpsis.utp.edu.co/www/paginas/Tutoriales/EstDatos/

Pgina 91 de 91