Professional Documents
Culture Documents
En ciencias de la informtica, un rbol es una estructura de datos ampliamente usada que imita la forma de un rbol (un conjunto de nodos conectados). Un nodo es la unidad sobre la que se construye el rbol y puede tener cero o ms nodos hijos conectados a l. Se dice que un nodo es padre de un nodo si existe un enlace desde hasta (en ese caso, tambin decimos que es hijo de ). Slo puede haber un nico nodo sin padres, que llamaremos raz. Un nodo que no tiene hijos se conoce como hoja. Los dems nodos (tienen padre y uno o varios hijos) se les conoce como rama.
Definicin
Formalmente, podemos definir un rbol de la siguiente forma:
Caso base: un rbol con slo un nodo (es a la vez raz del rbol y hoja). Un nuevo rbol a partir de un nodo y rboles de races con elementos cada uno, puede construirse estableciendo una relacin padre-hijo entre y cada una de las races de los rboles. El rbol resultante de nodos tiene como raz el nodo , los nodos son los hijos de y el conjunto de nodos hoja est formado por la unin de los conjuntos hojas iniciales. A cada uno de los rboles se les denota ahora subrboles de la raz.
Una sucesin de nodos del rbol, de forma que entre cada dos nodos consecutivos de la sucesin haya una relacin de parentesco, decimos que es un recorrido rbol. Existen dos recorridos tpicos para listar los nodos de un rbol: primero en profundidad y primero en anchura. En el primer caso, se listan los nodos expandiendo el hijo actual de cada nodo hasta llegar a una hoja, donde se vuelve al nodo anterior probando por el siguiente hijo y as sucesivamente. En el segundo, por su parte, antes de listar los nodos de nivel (a distancia aristas de la raz), se deben haber listado todos los de nivel . Otros recorridos tpicos del rbol son preorden, postorden e inorden:
El recorrido en preorden, tambin llamado orden previo consiste en recorrer en primer lugar la raz y luego cada uno de los hijos en orden previo. El recorrido en inorden, tambin llamado orden simtrico (aunque este nombre slo cobra significado en los rboles binarios) consiste en recorrer en primer lugar , luego la raz y luego cada uno de los hijos en orden simtrico. El recorrido en postorden, tambin llamado orden posterior consiste en recorrer en primer lugar cada uno de los hijos en orden posterior y por ltimo la raz.
Finalmente, puede decirse que esta estructura es una representacin del concepto de rbol en teora de grafos. Un rbol es un grafo conexo y acclico.
Tipos de rboles
Enumerar todos los elementos. Buscar un elemento. Dado un nodo, listar los hijos (si los hay). Borrar un elemento. Eliminar un subrbol (algunas veces llamada podar). Aadir un subrbol (algunas veces llamada injertar). Encontrar la raz de cualquier nodo.
Por su parte, la representacin puede realizarse de diferentes formas. Las ms utilizadas son:
Representar cada nodo como una variable en el heap, con punteros a sus hijos y a su padre. Representar el rbol con un array donde cada elemento es un nodo y las relaciones padre-hijo vienen dadas por la posicin del nodo en el array.
Representacin de datos jerrquicos. Como ayuda para realizar bsquedas en conjuntos de datos (ver tambin: algoritmos de bsqueda en rboles).
rbol binario
En ciencias de la computacin, un rbol binario es una estructura de datos en la cual cada nodo siempre tiene un hijo izquierdo y un hijo derecho. No pueden tener ms de dos hijos (de ah el nombre "binario"). Si algn hijo tiene como referencia a null, es decir que no almacena ningn dato, entonces este es llamado un nodo externo. En el caso contrario el hijo es llamado un nodo interno. Usos comunes de los rboles binarios son los rboles binarios de bsqueda, los montculos binarios y Codificacin de Huffman.
Un rbol binario sencillo de tamao 9, 4 niveles y altura 3 (altura = mximo nivel - 1), con un nodo raz cuyo valor es 2.
En teora de grafos, se usa la siguiente definicin: Un rbol binario es un grafo conexo, acclico y no dirigido tal que el grado de cada vrtice no es mayor a 3. De esta forma slo existe un camino entre un par de nodos. Un rbol binario con enraizado es como un grafo que tiene uno de sus vrtices, llamado raz, de grado no mayor a 2. Con la raz escogida, cada vrtice tendr un nico padre, y nunca ms de dos hijos. Si rehusamos el requerimiento de la conectividad, permitiendo mltiples componentes conectados en el grafo, llamaremos a esta ltima estructura un bosque.
Un rbol binario es un rbol con raz en el que cada nodo tiene como mximo dos hijos. Un rbol binario lleno es un rbol en el que cada nodo tiene cero o dos hijos. Un rbol binario perfecto es un rbol binario lleno en el que todas las hojas (vrtices con cero hijos) estn a la misma profundidad (distancia desde la raz, tambin llamada altura). A veces un rbol binario perfecto es denominado rbol binario completo. Otros definen un rbol binario completo como un rbol binario lleno en el que todas las hojas estn a profundidad n o n-1, para alguna n.
Un rbol binario es un rbol en el que ningn nodo puede tener ms de dos subrboles. En 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.
Implementacin en C
Un rbol binario puede declararse de varias maneras. Algunas de ellas son: Estructura con manejo de memoria dinmica, siendo puntA el puntero que apunta al rbol de tipo tArbol:
typedef struct nodo { int clave; struct nodo *izdo, *dcho; }Nodo;
En el caso de un rbol binario casi-completo (o un rbol completo), puede utilizarse un sencillo arreglo de enteros con tantas posiciones como nodos deba tener el rbol. La informacin de la ubicacin del nodo en el rbol es implcita a cada posicin del arreglo. As, si un nodo est en la posicin i, sus hijos se encuentran en las posiciones 2i+1 y 2i+2, mientras que su padre (si tiene), se encuentra en la posicin truncamiento((i-1)/2) (suponiendo que la raz est en la posicin cero). Este mtodo se beneficia de un almacenamiento ms compacto y una mejor localidad de referencia, particularmente durante un recorrido en preorden. La estructura para este caso sera por tanto:
int rbol[NUMERO_DE_NODOS];
El mtodo de este recorrido es tratar de encontrar de la cabecera a la raz en nodo de unidad binaria. Ahora pasamos a ver la implementacin de los distintos recorridos:
Recorrido en preorden
En este tipo de recorrido se realiza cierta accin (quizs simplemente imprimir por pantalla el valor de la clave de ese nodo) sobre el nodo actual y posteriormente se trata el subrbol
izquierdo y cuando se haya concluido, el subrbol derecho. Otra forma para entender el recorrido con este metodo seria seguir el orden: nodo raiz, nodo izquierda, nodo derecha. En el rbol de la figura el recorrido en preorden sera: 2, 7, 2, 6, 5, 11, 5, 9 y 4.
void preorden(tArbol *a) { if (a != NULL) { tratar(a); preorden(a->hIzquierdo); preorden(a->hDerecho); } }
Recorrido en postorden
En este caso se trata primero el subrbol izquierdo, despus el derecho y por ltimo el nodo actual. Otra forma para entender el recorrido con este metodo seria seguir el orden: nodo izquierda, nodo derecha, nodo raiz. En el rbol de la figura el recorrido en postorden sera: 2, 5, 11, 6, 7, 4, 9, 5 y 2.
void postorden(tArbol *a) { if (a != NULL) { postorden(a->hIzquiedo); postorden(a->hDerecho); tratar(a); } }
Recorrido en inorden
En este caso se trata primero el subrbol izquierdo, despus el nodo actual y por ltimo el subrbol derecho. En un ABB este recorrido dara los valores de clave ordenados de menor a
mayor. Otra forma para entender el recorrido con este metodo seria seguir el orden: nodo izquierda,nodo raiz,nodo derecha. En el rbol de la figura el recorrido en inorden sera: 2, 7, 5, 6, 11, 2, 5, 4, 9. Esquema de implementacin:
void inorden(tArbol *a) { if (a != NULL) { inorden(a->hIzquierdo); tratar(a); nodo inorden(a->hDerecho); } }
En este caso el recorrido se realiza en orden por los distintos niveles del rbol. As, se comenzara tratando el nivel 1, que slo contiene el nodo raz, seguidamente el nivel 2, el 3 y as sucesivamente. En el rbol de la figura el recorrido en amplitud sera: 2, 7, 5, 2, 6, 9, 5, 11 y 4. Al contrario que en los mtodos de recorrido en profundidad, el recorrido por niveles no es de naturaleza recursiva. Por ello, se debe utilizar una cola para recordar los subrboles izquierdos y derecho de cada nodo. El esquema algoritmo para implementar un recorrido por niveles es exactamente el mismo que el utilizado en la versin iterativa del recorrido en preorden pero cambiando la estructura de datos que almacena los nodos por una cola. Implementacin en C:
void arbol_recorrido_anch (tipo_Arbol* A) { tipo_Cola cola_nodos; // esta cola esta implementada previamente, almacena punteros (posiciones de nodos de arbol) tipo_Pos nodo_actual; // este es un puntero llevara el recorrido if (vacio(A)) // sie el arbol esta vacio, salimos return; cola_inicializa(&cola_nodos); // obvio, y necesario cola_enqueue(A, &cola_nodos); // se encola la raiz while (!vacia(&cola_nodos)) { // mientras la cola no se vacie se realizara el recorrido nodo_actual = cola_dequeue(&cola_nodos) // de la cola saldran los nodos ordenados por nivel
printf("%c,", nodo_actual->info); // se "procesa" el nodo donde va el recorrido, en este caso se imprime if (nodo_actual->izq != null) // si existe, ponemos el hijo izquierdo en la cola cola_enqueue(nodo_actual->izq, &cola_nodos); if (nodo_actual->der != null) // si existe, ponemos el hijo derecho en la cola cola_enqueue(nodo_actual->der, &cola_nodos); arbol } } // al vaciarse la cola se han visitado todos los nodos del
Los rboles binarios tambin pueden ser almacenados como una estructura de datos implcita en vectores, y si el rbol es un rbol binario completo, este mtodo no desaprovecha el espacio en memoria. Tomaremos como notacin la siguiente: si un nodo tiene un ndice i, sus hijos se encuentran en ndices 2i + 1 y 2i + 2, mientras que sus padres (si los tiene) se encuentra en el ndice (partiendo de que la raz tenga ndice cero). Este mtodo tiene como ventajas el tener almacenados los datos de forma ms compacta y por tener una forma
ms rpida y eficiente de localizar los datos en particular durante un preoden transversal. Sin embargo, desperdicia mucho espacio en memoria.
Que se ejecutar en la memoria como el rbol binario de la derecha, sin ningn tipo de letras en aquellos nodos que tienen un hijo izquierdo.
Un rbol es una estructura no lineal en la que cada nodo puede apuntar a uno o varios nodos. Tambin se suele dar una definicin recursiva: un rbol es una estructura en compuesta por un dato y varios rboles. Esto son definiciones simples. Pero las caractersticas que implican no lo son tanto.
Nodo hijo: cualquiera de los nodos apuntados por uno de los nodos del rbol. En el ejemplo, 'L' y 'M' son hijos de 'G'. Nodo padre: nodo que contiene un puntero al nodo actual. En el ejemplo, el nodo 'A' es padre de 'B', 'C' y 'D'.
Los rboles con los que trabajaremos tienen otra caracterstica importante: cada nodo slo puede ser apuntado por otro nodo, es decir, cada nodo slo tendr un padre. Esto hace que estos rboles estn fuertemente jerarquizados, y es lo que en realidad les da la apariencia de rboles. En cuanto a la posicin dentro del rbol:
Nodo raz: nodo que no tiene padre. Este es el nodo que usaremos para referirnos al rbol. En el ejemplo, ese nodo es el 'A'. Nodo hoja: nodo que no tiene hijos. En el ejemplo hay varios: 'F', 'H', 'I', 'K', 'L', 'M', 'N' y 'O'. Nodo rama: aunque esta definicin apenas la usaremos, estos son los nodos que no pertenecen a ninguna de las dos categoras anteriores. En el ejemplo: 'B', 'C', 'D', 'E', 'G' y 'J'.
Otra caracterstica que normalmente tendrn nuestros rboles es que todos los nodos contengan el mismo nmero de punteros, es decir, usaremos la misma estructura para todos
los nodos del rbol. Esto hace que la estructura sea ms sencilla, y por lo tanto tambin los programas para trabajar con ellos. Tampoco es necesario que todos los nodos hijos de un nodo concreto existan. Es decir, que pueden usarse todos, algunos o ninguno de los punteros de cada nodo. Un rbol en el que en cada nodo o bien todos o ninguno de los hijos existe, se llama rbol completo. En una cosa, los rboles se parecen al resto de las estructuras que hemos visto: 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. Existen otros conceptos que definen las caractersticas del rbol, en relacin a su tamao:
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. Grado: el nmero de hijos que tiene el elemento con ms hijos dentro del rbol. En el rbol del ejemplo, el grado es tres, ya que tanto 'A' como 'D' tienen tres hijos, y no existen elementos con ms de tres hijos. Nivel: se define para cada elemento del rbol como la distancia a la raz, medida en nodos. El nivel de la raz es cero y el de sus hijos uno. As sucesivamente. En el ejemplo, el nodo 'D' tiene nivel 1, el nodo 'G' tiene nivel 2, y el nodo 'N', nivel 3. 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, tambin podemos hablar de altura de ramas. El rbol del ejemplo tiene altura 3, la rama 'B' tiene altura 2, la rama 'G' tiene altura 1, la 'H' cero, etc.
Los rboles de orden dos son bastante especiales, de hecho les dedicaremos varios captulos. Estos rboles se conocen tambin como rboles binarios. 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. Es importante conservar siempre el nodo raz ya que es el nodo a partir del cual se desarrolla el rbol, si perdemos este nodo, perderemos el acceso a todo el rbol. El nodo tpico de un rbol difiere de los nodos que hemos visto hasta ahora para listas, aunque slo en el nmero de nodos. Veamos un ejemplo de nodo para crear rboles de orden tres:
struct nodo \{ int dato; struct nodo *rama1; struct nodo *rama2;
O generalizando ms:
#define ORDEN 5 struct nodo \{ int dato; struct nodo *rama[ORDEN]; };
Al igual que hicimos con las listas que hemos visto hasta ahora, declaramos un tipo tipoNodo para declarar nodos, y un tipo pNodo para es el tipo para declarar punteros a un nodo. Arbol es el tipo para declarar rboles de orden ORDEN.
rbol El movimiento a travs de rboles, salvo que implementemos punteros al nodo padre, ser siempre partiendo del nodo raz hacia un nodo hoja. Cada vez que lleguemos a un nuevo nodo podremos optar por cualquiera de los nodos a los que apunta para avanzar al siguiente nodo.
En general, intentaremos que exista algn significado asociado a cada uno de los punteros dentro de cada nodo, los rboles que estamos viendo son abstractos, pero las aplicaciones no tienen por qu serlo. Un ejemplo de estructura en rbol es el sistema de directorios y ficheros de un sistema operativo. Aunque en este caso se trata de rboles con nodos de dos tipos, nodos directotio y nodos fichero, podramos considerar que los nodos hoja son ficheros y los nodos rama son directorios. Otro ejemplo podra ser la tabla de contenido de un libro, por ejemplo de este mismo curso, dividido en captulos, y cada uno de ellos en subcaptulos. Aunque el libro sea algo lineal, como una lista, en el que cada captulo sigue al anterior, tambin es posible acceder a cualquier punto de l a travs de la tabla de contenido. Tambin se suelen organizar en forma de rbol los organigramas de mando en empresas o en el ejrcito, y los rboles genealgicos.