Anda di halaman 1dari 42

RBOLES BlNARlOS

Un rbol binario es un rbol en el que ningn nodo

puede tener ms de dos subrboles. Es un rbol binario, cada nodo puede tener, cero, uno o dos hijos (subrboles). Se conoce el nodo de la izquierda como hijo izquierdo y el nodo de la derecha como hijo derecho. Es una estructura recursiva. Cada nodo es el raz de su propio subrbol y tiene hijos, que son races de rboles llamados los subrboles derecho e izquierdo del nodo, respectivamente.

Ejemplos de nodos binarios

rbol degenerado, en el que existe un solo nodo hoja

( E ) y cada nodo no hoja slo tiene un hijo. Un rbol degenerado es equivalente a una lista enlazada.

Equilibrio
Para determinar si un rbol est equilibrado, se calcula su factor de equilibrio.

El factor de equilibrio de un rbol binario es la diferencia en altura entre los subrboles derecho e izquierdo. Si definimos la altura del subrbol izquierdo como Hi, y la altura del subrbol derecho como Hd, entonces el factor de equilibrio del rbol B se determina por la siguiente frmula: B = Hd - Hi.
Un rbol est perfectamente equilibrado si su equilibrio o balance es cero y

sus subrboles son tambin perfectamente equilibrados. Dado que esta definicin ocurre raramente se aplica una definicin alternativa. Un rbol binario est equilibrado si la altura de sus subrboles difiere en no ms de uno (su factor de equilibrio es -1, 0, + 1 ) y sus subrboles son tambin equilibrados.

Estructura de un rbol binario

Representacin de un rbol en C
typedef int TipoElemento; struct Nodo { TipoElemento dato; struct Nodo *izdo, *dcho; }; typedef struct Nodo ElementoDeArbolBin; typedef ElementoDeArbolBin *ArbolBinario;

Crear nodo
ArbolBinario CrearNodo(TipoE1emento x) { ArbolBinario a; a=(ArbolBinario) malloc(sizeof(ElementoDeArbolBin)); a->dato = x; a->dcho=a->izdo=NULL; return a; }

Ejemplo

ArbolBinario raiz; raiz = CrearNodo(9); raiz -> izdo = CrearNodo(7); raiz -> dcho = CrearNodo(11);

OPERACIONES EN RBOLES BINARIOS


ArbolBinario CrearNodo(TipoE1emento x) { ArbolBinario a; a=(ArbolBinario) malloc(sizeof(ElementoDeArbolBin)); a->dato = x; a->dcho=a->izdo=NULL; return a; } void nuevoArbol(ArbolBinario* raiz, ArbolBinario ramaIzqda, TipoElemento x, ArbolBinario ramaDrcha) { *raiz=CrearNodo(x); (*raiz)->izdo=ramaIzqda; (*raiz)->dcho=ramaDrcha(); }

OPERACIONES EN RBOLES BINARIOS


ArbolBinario raiz,a1,a2; Pila pila; nuevoArbol(&a1,NULL,1,NULL); nuevoArbol(&a2,NULL,2,NULL); nuevoArbol(&raiz,a1,3,a2); insertar(&pila,raiz); nuevoArbol(&a1,NULL,4,NULL); nuevoArbol(&a2,NULL,5,NULL); nuevoArbol(&raiz,a1,6,a2); insertar(&pila,raiz); a2=quitar(&pila); a1=quitar(&pila); nuevoArbol(&raiz,a1,7,a2);

OPERACIONES EN RBOLES BINARIOS


int profundidad (ArbolBinario raiz) { if (!raiz) return 0 ; else { int profundidadI, profundidadD; profundidadI = profundidad (raiz -> izdo); profundidadD = profundidad (raiz -> dcho); if (profundidadI > profundidadD) return profundidadI + 1; else return profundidadD + 1;

}
}

OPERACIONES EN RBOLES BINARIOS


int altura(ArbolBinario r) { if (r == NULL) return 0; else return (1 + max(altura(r->izdo),altura(r->dcho))); }

OPERACIONES EN RBOLES BINARIOS


void contarhojas(ArbolBinario r, int* nh) { if (r != NULL) { contarhojas(r -> izdo, nh); contarhojas(r -> dcho, nh); /* procesar raz: determinar si es hoja */

if (r->izdo=NULL && r->dchoa==NULL) (*nh)++;


} }

OPERACIONES EN RBOLES BINARIOS


void eliminarbol(ArbolBinario r) { if (r != NULL) { eliminarbol(r -> izdo); eliminarbol(r -> dcho); printf("\tNodo borrado: %d ",r -> dato); free(r); } }

Recorridos o visitas de rbol binario


consiste en visitar una sola vez cada nodo del rbol. Los recorridos son importantes para las operaciones

de bsqueda, insercin y borrado. En el programa de recorrido de funciones, es deseable tratar todos los nodos de la misma manera. Definamos las siguientes operaciones:
N I D

Nodo Izquierda Derecha

Existen seis posibles combinaciones para aplicar estas

operaciones que son: {IND, IDN, NID, NDI, DNI, DIN} Adoptando la convencin de que siempre recorrer izquierda antes que derecha del conjunto anterior tenemos: {IND, IND, NID} que son los recorridos que conocemos
NID IDN IND

Pre-orden, Post-orden En orden

Los compiladores usan estructuras rbol para pre-

procesar almacenar y calcular expresiones:

void preorden (ArbolBinario raiz) { if (raiz != NULL) { visitar(raiz -> dato); preorden(raiz -> izdo); preorden(raiz -> dcho); } }

void enorden (ArbolBinario raiz) { if (raiz != NULL) { enorden(raiz -> izdo); visitar(raiz -> dato); enorden (raiz -> dcho); } }

void postorden (ArbolBinario raiz) { if (raiz) { postorden (raiz -> izdo); postorden (raiz -> dcho); visitar(raiz -> dato); } }

RBOLES BINARIOS DE BSQUEDA

rboles binarios de bsqueda (ABB)


Los rboles vistos hasta ahora no tienen un orden

definido; sin embargo, los rboles binarios ordenados tienen sentido. Estos rboles se denominan rboles binarios de bsqueda, debido a que se pueden buscar en ellos un trmino utilizando un algoritmo de bsqueda binaria. Un rbol binario de bsqueda es aquel que dado un nodo, todos los datos del subrbol izquierdo son menores que los datos de ese nodo, mientras que todos los datos del subrbol derecho son mayores que sus propios datos.

Ejemplo
30 menor que 55 41 mayor que 30 75 mayor que 55 85 mayor que 75 4 menor que 30
4 55

30
41

75 85

Creacin de un ABB
Supongamos que se desean almacenar los nmeros 8 3 1

20 10 5 4 en un rbol binario de bsqueda. Siguiendo la regla, dado un nodo en el rbol todos los datos a su izquierda deben ser menores que todos los datos del nodo actual, mientras que todos los datos a la derecha deben ser mayores que los datos. Inicialmente el rbol est vaco y se desea insertar el 8. La nica eleccin es almacenar el 8 en el raz:
8

Creacin de un ABB
A continuacin viene el 3. Ya que 3 es

menor que 8, el 3 debe ir en el subrbol izquierdo. A continuacin se ha de insertar 1 que es menor que 8 y que 3, por consiguiente ir a la izquierda y debajo de 3. El siguiente nmero es 20, mayor que 8, lo que implica debe ir a la derecha de 8.
Cada nuevo

8 3 1 20 10 5 4
8 3 1 4 20

10

elemento se inserta como una hoja del rbol. Los restantes elementos se pueden situar fcilmente.

Ejemplo
Construir un rbol binario para almacenar los datos

12, 8, 7, 16 y 14.
12 8 16

14

Operaciones en un ABB
De lo expuesto se deduce que los rboles binarios

tienen naturaleza recursiva y en consecuencia las operaciones sobre los rboles son recursivas, si bien siempre tenemos la opcin de realizarlas de forma iterativa. Estas operaciones son:
Bsqueda de un nodo. Insercin de un nodo. Recorrido de un rbol.

Borrado de un nodo.

Bsqueda
La bsqueda de un nodo comienza en el nodo raz y

sigue estos pasos:


1. 2. 3.

La clave buscada se compara con la clave del nodo raz. Si las claves son iguales, la bsqueda se detiene. Si la clave buscada es mayor que la clave raz, la bsqueda se reanuda en el subrbol derecha. Si la clave buscada es menor que la clave raz, la bsqueda se reanuda con el subrbol izquierdo.

La terminacin del procedimiento se produce cuando:


Se encuentra la clave. Alcanza un subrbol vaco: la clave buscada no est en el

rbol

Bsqueda
Nodo* buscar (Nodo* p, int buscado) { if (!p) return 0; else if (buscado == p -> dato) return p; else if (buscado < p -> dato) return buscar (p -> izdo, buscado); else return buscar (p -> dcho, buscado); }

Bsqueda
Nodo* buscar (Nodo* raiz, int buscado) { Nodo *a = raiz; int encontrado = 0; while (a != NULL && !encontrado) { if (buscado == a -> dato) encontrado = 1; else if (buscado < a -> dato) a = a -> izdo; else if (buscado > a -> dato) a = a -> dcho; } return a; }

Insertar en un ABB
Una caracterstica fundamental que debe poseer el

algoritmo de insercin es que el rbol resultante de una insercin en un rbol de bsqueda ha de ser tambin de bsqueda. En esencia, el algoritmo de insercin se apoya en la localizacin de un elemento, de modo que si se encuentra el elemento (clave) buscado, no es necesario hacer nada; en caso contrario, se inserta el nuevo elemento justo en el lugar donde ha acabado la bsqueda (es decir, en el lugar donde habra estado en el caso de existir).

Ejemplo
Insertar el elemento 80 en el rbol binario de

bsqueda siguiente: A continuacin insertar un elemento con clave 36 en el rbol binario de bsqueda resultante
30
5 2 36

40
80

Insertar
La funcin insertar() aade una clave al rbol de bsqueda, el

algoritmo de insercin realiza las mismas acciones para cada subrbol, comparar con el raz u continuar por rama izquierda o derecha, es un algoritmo recursivo y entonces la implementacin recursiva es sumamente sencilla. La funcin tiene el argumento puntero a la raz del rbol, adems los argumentos de la clave y dems datos asociados (int). La funcin crear un nuevo nodo y lo inserta en el lugar correcto en el rbol de modo que el rbol siga siendo binario de bsqueda. de bsqueda. Los pasos a seguir son:
1. 2.

La operacin de insercin de un nodo es una extensin de la operacin

3.

Asignar memoria para una nueva estructura nodo. Buscar en el rbol para encontrar la posicin de insercin del nuevo nodo, que se colocar como nodo hoja. Enlazar el nuevo nodo al rbol.

void insertar (Nodo** raiz, int nuevoDato) { if (!(*raiz)) *raiz = CrearNodo(nuevoDato); else if (nuevoDato < (*raiz) -> dato) insertar (&((*raiz) -> izdo), nuevoDato); else insertar (&((*raiz) -> dcho), nuevoDato); }

Eliminacin
La operacin de eliminacin de un nodo es tambin una

extensin de la operacin de bsqueda, si bien ms compleja que la insercin debido a que el nodo a suprimir puede ser cualquiera y la operacin de supresin debe mantener la estructura de rbol binario de bsqueda despus de la eliminacin de datos. Los pasos a seguir son:
1. 2.

Buscar en el rbol para encontrar la posicin de nodo a eliminar. Reajustar los punteros de sus antecesores si el nodo a suprimir tiene menos de 2 hijos, o subir a la posicin que ste ocupa el nodo ms prximo en clave (inmediatamente superior o inmediatamente inferior) con objeto de mantener la estructura de rbol binario.

Ejemplo
Eliminar el elemento 36.

30

5
2 36

40 80

Ejemplo
Eliminar el elemento 60
40
20 10 30 45 54

40

60 50
55 70 10

20 30 45 50

55 70 54

Eliminar
La eliminacin de un elemento debe conservar el orden de

los elementos de rbol. Se consideran diferentes casos, segn sea la posicin del nodo en el rbol: Si el nodo es una hoja, se suprime simplemente Si el nodo no tiene ms que un descendiente, se sutituye entonces por ese descendiente. Si el nodo tiene dos descendientes, se sustituye por el nodo inmediato inferior que se encuentra lo ms a la derecha posible del subrbol izquierdo (se puede seguir la alternativa de sustituir por el nodo inmediato superior que se encuentra lo ms a la izquierda posible del subrbol derecho).

Eliminar
void eliminar (Nodo** raiz, int clave) { if (!(*raiz)) puts("!! Nodo no encontrado !!"); else if (clave < (*raiz) -> dato) eliminar(&(*raiz) -> izdo, clave); else if (clave > (*raiz) -> dato) eliminar(&(*raiz) -> dcho, clave); else /* Nodo encontrado */ { Nodo* q; /* puntero al nodo a suprimir */ q = (*raiz); if (q -> izdo == NULL) (*raiz) = q -> dcho; else if (q -> dcho == NULL) (*raiz) = q -> izdo; else { /* tiene rama izquierda y derecha */ reemplazar(&q); } free(q); } }

Reemplazar
void reemplazar(Nodo** act) { Nodo* a, *p; p = *act; a = (*act) -> izdo; /* rama de menores */ while (a -> dcho) { p = a; a = a -> dcho; } (*act) -> dato = a -> dato; if (p == (*act)) p -> izdo = a -> izdo; else p -> dcho = a -> izdo; (*act) = a; }