Arboles de Mate Dizcretas Sin Autor

Descargar como doc, pdf o txt
Descargar como doc, pdf o txt
Está en la página 1de 9

Construcción del árbol de Huffman

Para construir un código de Huffman normalmente se utiliza un árbol binario que se construye a partir de las
probabilidades de los símbolos que deseamos codificar. El diseño de dicho árbol se realiza de la siguiente forma:

Algoritmo de creación del árbol de Huffman

1.
Crear tantos nodos (que serán las hojas del árbol) como símbolos vayamos a codificar. En cada
nodo almacenaremos el símbolo codificado y su probabilidad. Estos nodos forman la lista de nodos
sin procesar.
2.
Extraer dos nodos de la lista de nodos sin procesar que tengan una probabilidad mínima.
3.
Insertar en la lista un nodo que sea padre de los dos nodos seleccionados. Este nodo no tiene
asociado ningún símbolo y su probabilidad será la suma de las probabilidades de los nodos hijo.
4.
Repetir los pasos 2 y 3 hasta que únicamente tengamos un nodo en la lista de nodos sin procesar,
nodo que debe tener una probabilidad igual a 1 y que se llama nodo raíz del árbol de Huffman.

Puesto que en cada iteración extraemos dos nodos de la lista e insertamos otro, el número de iteraciones necesarias
para construir un árbol con N hojas (el número de símbolos que deseamos codificar) es N. Una vez construido el
árbol, el código de compresión asociado a un símbolo se calcula recorriendo el árbol desde la raíz hasta el símbolo
codificado (situado siempre en una hoja). Veamos un ejemplo de codificación.

  
Figura 3: Ejemplo de construcción de un árbol de
Huffman. (A) inicialmente el árbol es un bosque de 5
nodos. (B) Se agrupan los dos nodos de menor peso. Se
extrae de la lista de nodos sin procesar los nodos D y E,
y se inserta un nodo con la suma (igual a 11) de sus
pesos. (C) Los siguientes dos nodos de menor peso de la
lista de nodos sin procesar son los nodos B y C. (D) se
procesan los nodos de peso 13 y 11 y (E) se termina de
construir el árbol.

Por comodidad trabajaremos con pesos enteros y no con probabilidades reales. Así, para construir el árbol de
Huffman, partiremos de que vamos a codificar 5 símbolos distintos A,B,C,D y E con pesos 15, 7, 6, 6 y 5
respectivamente. Todo el proceso se describe en la figura 3. El primer paso (figura 3-A) consiste en crear una lista
de nodos sin procesar. Gráficamente esta lista estará formada por los nodos que queden en el nivel superior. A
continuación extraemos de la lista los nodos con símbolos D y E por ser los de menor peso. También podríamos
seleccionar el nodo con símbolo C. El árbol resultante sería diferente (los códigos pueden variar tanto de valor
como de longitud) pero equivalente desde el punto de vista de la compresión de datos. Los pesos de los nodos D y
E son 6 y 5. Por tanto, insertamos un nuevo nodo en la lista, sin símbolo asociado y con un peso igual a 11
(figura 3-B). Los dos siguientes nodos utilizados para construir un nuevo subárbol son el B y el C (figura 3-C). A
continuación los dos subárboles forman un árbol mayor (figura 3-D) y por último, el nodo A se procesa quedando
el árbol de Huffman completo (figura 3-E).

Técnicas básicas de búsqueda:

BÚSQUEDA EN GRAFOS

Para efectuar una búsqueda de los vértices de un grafo, se pueden emplear dos estrategias diferentes:

Búsqueda en profundidad (BEP): Se comienza en cualquier vértice y en cada paso se avanza a un nuevo vértice

adyacente siempre que se pueda. Cuando todos los adyacentes a X hayan sido visitados, se retrocede al vértice

desde el que se alcanzó X y se prosigue. Así se consigue etiquetar (visitar) todos los vértices de la componente

conexa en que se encuentre el vértice inicial.

Esta técnica se utiliza cuando necesitamos encontrar respuesta a un problema sobre un grafo sin condiciones de
optimización.

La idea en general de la búsqueda en profundidad comenzando en un nodo A es la siguiente:

Primero examinamos el nodo inicial A. Luego examinamos cada nodo N de un camino P que comience en A; a
sea, procesamos un vecino de A, luego un vecino de un vecino de A y así sucesivamente, hasta llegar a un punto
muerto o final del camino P, y de aquí volvemos atrás por P hasta que podamos continuar por otro camino P´ y así
sucesivamente.

Este algoritmo es similar al del recorrido inorden de un árbol binario, y también a la forma en que se debe pasar a
través de un laberinto. Observe que se hace uso una pila en lugar de una cola, y este es el detalle fundamental que
hace la diferencia para realizar la búsqueda en profundidad.

 
Algoritmo para la búsqueda en profundidad:

Este algoritmo realiza la búsqueda en profundidad el grafo G comenzando en un nodo A.

1.     Inicializar todos los nodos al estado de preparado (ESTADO=1)

2.     Meter el nodo inicial A en la pila y cambiar su estado a estado de espera (ESTADO=2).

3.     Repetir los pasos 4 y 5 hasta que la pila este vacia.

4.     Sacar el nodo N en la cima de la pila. Procesar el nodo N y cambiar su

estado al de procesado (ESTADO=3).

5.     Meter en la pila todos los vecinos de N que estén en estado de

preparados (ESTADO=1) y cambiar su estado a estado de espera

(ESTADO=2).

[ fin de bucle del paso 3 ]

6.     Salir.

nota: tomado del libro Estructura de datos, serie schaum Mcgraw-Hill,

pagina: 337, capitulo: 8 Grafos y sus aplicaciones, autor: Seymour Lipschutz

Búsqueda en anchura (BEA): A diferencia con la BEP ahora se visitan todos los vecinos de un vértice antes de
pasar al siguiente. Por tanto no hay necesidad de retroceder. Una vez etiquetados todos los vecinos de un vértice X,
se continúa con el primer vértice alcanzado después de X en la búsqueda.

Esta técnica se utiliza para resolver problemas en los que se pide hallar una solución óptima entre varias.

En general la búsqueda en anchura comenzando de un nodo de partida A es la siguiente:

Primero examinamos el nodo de partida A.

Luego examinamos todos los vecinos de A. Luego examinamos todos los vecinos de los vecinos de A y así

sucesivamente. Con el uso de una cola, garantizamos que ningún nodo sea procesado más de una vez y usando un

campo ESTADO que nos indica el estado actual de los nodos.


 

Algoritmo para la búsqueda en anchura:

Este algoritmo realiza la búsqueda en anchura en un grafo G comenzando en un nodo de partida A.

1.     Inicializar todos los nodos al estado de preparados (ESTADO=1).

2.     Poner el nodo de partida A en la COLA y cambiar su estado a espera (ESTADO=2).

3.     Repetir pasos 4 y 5 hasta que COLA esté vacía.

4.     Quitar el nodo del principio de la cola, N. Procesar N y cambiar su

estado a procesado (ESTADO=3).

5.     Añadir a COLA todos los vecinos de N que estén en estado de

preparados (ESTADO=1) y cambiar su estado al de espera

(ESTADO=2).

[ fin del bucle del paso 3 ]

6.     Salir.

nota: tomado del libro Estructura de datos, serie schaum Mcgraw-Hill,

pagina: 334 - 335, capitulo: 8 Grafos y sus aplicaciones, autor: Seymour Lipschutz

Árboles binarios
Los árboles binarios son estructuras matemáticas que organizan un conjunto de elementos. Supondremos en este
ejercicio que en un mismo árbol no puede haber elementos repetidos. Cada elemento se almacena en un nodo.
Algunos de los nodos pueden estar relacionados, y son estas relaciones las que definen el árbol. Definimos un árbol
binario de la manera siguiente:
 El árbol vacío es un árbol binario que no contiene ningún nodo.
 Dados dos árboles binarios  y  y dado un elemento x, se puede formar un tercer árbol binario  enraizando  y
 con un nodo que almacene x. Diremos que el nuevo nodo que almacena x es la raíz de ,  es el subárbol
izquierdo de , y  el subárbol derecho. Diremos también que la raíz de  es el hijo izquierdo de la raíz de ,
la raíz de  es el hijo derecho de la raíz de  y, por consiguiente, la raíz de  es el padre de las raíces de ambos
subárboles.
En la figura siguiente se muestra un ejemplo de árbol binario:
A: raíz del árbol
A: padre de C y de E
C: hijo izquierdo de A
E: hijo derecho de A
Notemos pues que los nodos de un árbol binario pueden tener 0, 1 ó 2 hijos.

1.- Dado un árbol binario  con letras mayúsculas almacenadas en los nodos (es decir, con un máximo de 26
nodos, pues excluimos la 'Ñ' y la 'Ç'), se define su recorrido en preorden como un listado de los elementos
contenidos en sus nodos según la definición siguiente:
 Si  es un árbol vacío, se da por finalizado su recorrido.
 Si no, el primer elemento del listado es el contenido en la raíz de .
 A continuación, aparecen en preorden los elementos del subárbol izquierdo de .
 Por último, aparecen en preorden los elementos del subárbol derecho de .
El recorrido en preorden del árbol de la figura anterior es: A C B E F D.
Nos proponemos construir un programa que calcule el recorrido en preorden de un árbol binario. El árbol residirá
en el fichero "ARB1.DAT", que consta de una serie de líneas que definen qué nodos son padres de cuáles otros.
Cada línea consta de exactamente de cinco caracteres:
 Una letra mayúscula que identifica un nodo.
 Un carácter blanco.
 Una letra mayúscula que identifica otro nodo.
 Un carácter blanco.
 Un símbolo que puede ser: o bien '<', que indica que el segundo nodo es hijo izquierdo del primero, o bien '>',
que indica que el segundo nodo es hijo derecho del primero.
Puede suponerse que la entrada permite construir un árbol binario correcto (es decir, donde todo nodo tenga un
único padre, excepto uno de ellos que es la raíz; donde todo nodo tiene como máximo un hijo izquierdo y un hijo
derecho; y donde no hay caracteres repetidos). El árbol de la figura anterior puede representarse con el fichero de
entrada siguiente (o con cualquier otro que sea una simple permutación de sus líneas):

ARB1.DAT
CB>
EF<
AC<
ED>
AE>

La salida "ARB1.RES" será una única línea que mostrará el listado resultante de recorrer el árbol en preorden,
escribiendo un carácter blanco después de cada contenido de nodo.

2.- Definimos el recorrido en inorden de un árbol binario A de manera similar al preorden:


 Si  es un árbol vacío, se da por finalizado su recorrido.
 Si no, primero aparecen en inorden los elementos del subárbol izquierdo de .
 A continuación, aparece el contenido en la raíz de .
 Por último, aparecen en inorden los elementos del subárbol derecho de .
El recorrido en inorden del árbol de la figura anterior es: C B A F E D.
Puede demostrarse que un árbol binario se puede reconstruir a partir de sus recorridos en preorden e inorden, y se
pide un programa que efectúe este proceso. El fichero de entrada, "ARB2.DAT", contendrá dos líneas, la primera
con el recorrido en preorden y la segunda con el recorrido en inorden. En cada una de estas líneas aparecerá un
carácter blanco después de cada contenido de nodo. Puede suponerse la corrección de este juego de pruebas. El
fichero de salida "ARB2.RES" contiene el árbol en el mismo formato que el fichero de entrada "ARB1.DAT" del
apartado anterior, con la única diferencia que se exige una ordenación determinada en las líneas de salida: deben
estar ordenadas alfabéticamente según el primer elemento y, si un nodo tiene los dos hijos, debe aparecer antes el
contenido del hijo izquierdo que el del hijo derecho.
A continuación se muestran los ficheros correspondientes al árbol ejemplo del apartado anterior:

ARB2.DAT ARB2.RES
ACBEFD AC<
CBAFED AE>
CB>
EF<
ED>

3.- Se pretende ahora obtener todos los árboles que tengan un mismo recorrido en preorden para un conjunto de
elementos dado. El fichero de entrada "ARB3.DAT" estará formado por una única línea que contendrá letras
mayúsculas (sin repetición) con un blanco a continuación de cada una de ellas, representando un recorrido en
preorden. El fichero de salida "ARB3.RES" tendrá una línea inicial que dirá cuantos árboles pueden formarse que
tengan ese recorrido en inorden (representación del entero mediante dígitos –caracteres entre el ‘0’ y el ‘9’) y, a
continuación, la representación de todos esos árboles con el mismo formato que el fichero "ARB1.DAT" del
primer apartado. Detrás de cada árbol habrá una línea que contendrá un único carácter '$'. Los árboles deben
aparecer en la salida por orden alfabético de su recorrido inorden. En cada árbol individual, se exige la misma
ordenación de sus líneas que en el apartado anterior: deben estar ordenadas alfabéticamente por el contenido del
primer nodo y, si un nodo tiene los dos hijos, debe aparecer antes el contenido del hijo izquierdo que el del hijo
derecho.
He aquí un ejemplo. Los cinco árboles posibles para el recorrido en preorden dado tienen el siguiente recorrido en
inorden: A B C, A C B, B A C, B C A, C B A, con lo que cumplen la condición de ordenación impuesta por el
enunciado:

ARB3.DAT ARB3.RES
ABC 5
AB>
BC>
$
AB>
BC<
$
AB<
AC>
$
AB<
BC>
$
AB<
BC<
$

4.- Un árbol binario de búsqueda es un árbol binario que se define de la manera siguiente:
 Todo árbol vacío es un árbol binario de búsqueda.
 Un árbol binario no vacío  es un árbol binario de búsqueda si cumple:
 Si  tiene subárbol izquierdo, entonces debe cumplirse a la vez que:
 la raíz de  sea mayor que el valor máximo almacenado en el subárbol izquierdo de , y
 el subárbol izquierdo de  sea un árbol de búsqueda
 Si  tiene subárbol derecho, entonces debe cumplirse a la vez que:
 la raíz de  sea menor que el valor mínimo almacenado en el subárbol derecho de , y
 el subárbol derecho de  sea un árbol de búsqueda
El interés de los árboles binarios de búsqueda radica en que su recorrido en inorden proporciona los elementos
ordenados.
Por ejemplo, en la figura siguiente, el árbol de la izquierda es un árbol de búsqueda, mientras que los otros no lo
son: en el primero de ellos, la raíz es menor (consideramos el orden alfabético) que el máximo del subárbol
derecho, mientras que en el segundo, el subárbol derecho no es de búsqueda.
Se pide que construyáis un programa que, dado un árbol binario de búsqueda, inserte unos cuantos elementos de
manera que, después de cada inserción individual, el árbol siga siendo de búsqueda. Por ejemplo, si se quiere
insertar la B, la H y la F en el árbol de la izquierda de la figura anterior, el resultado después de cada operación
sería:

E E E

A I A I A I

C G K C G K C G K

B B H B F H

El fichero de entrada "ARB4.DAT" contendrá primero el árbol binario de búsqueda con el formato habitual (el
mismo que "ARB1.DAT"). A continuación, aparecerá una línea que contendrá un único carácter '$'. Finalmente,
una nueva línea que contendrá los elementos a insertar (letras mayúsculas, sin repeticiones, que supondremos no
existirán en el árbol de partida), con un único carácter blanco después de cada una. El fichero de salida contendrá
los árboles correspondientes a cada inserción en el mismo orden que se efectúan éstas. Detrás de cada árbol
aparecerá una línea que contendrá un único carácter '$'. En cada árbol individual, se exige la misma ordenación de
sus líneas que en el apartado anterior: deben estar ordenadas alfabéticamente por el contenido del primer nodo y, si
un nodo tiene los dos hijos, debe aparecer antes el contenido del hijo izquierdo que el del hijo derecho. A
continuación se muestra un posible fichero de entrada para el ejemplo anterior, y la salida correspondiente:

ARB4.DAT ARB4.RES
EA< AC>
AC> CB<
IK> EA<
IG< EI>
EI> IG<
$ IK>
BHF $
AC>
CB<
EA<
EI>
GH>
IG<
IK>
$
AC>
CB<
EA<
EI>
GF<
GH>
IG<
IK>
$

También podría gustarte