Está en la página 1de 37

12.

3 Arboles y ordenaciones
•En  el capitulo 10 (ejemplo 10.4) se trabajo con la ordenación por el
método de la burbuja en el estudio de las relaciones de recurrencia
lineales. Vimos que para el numero de comparaciones necesarias una
lista de n elementos es . En consecuencia, este algoritmo determina
una función dada por . Esta es la función de complejidad en el tiempo
(para el peor caso) del algoritmo y la expresamos escribiendo . En
consecuencia, la ordenación por el método de la burbuja necesita
comparaciones. Interpretamos esto diciendo que para una n grande, el
numero de comparaciones es igual a , donde c es una constante de
proporcionalidad que generalmente no se especifica, pues depende de
factores como el compilador y el computador utilizados.
12.3 Arboles y ordenaciones
•En  esta sección analizaremos un segundo método para ordenar una lista
dada de n elementos en orden ascendente. Este método se llama
ordenamiento por inserción y veremos que el orden de su función de
complejidad en tiempo para el peor caso es Haremos esto de la manera
siguiente:
1. Primero estimaremos el numero de comparaciones necesarias cuando
n es una potencia de dos. Nuestro método utilizará un par de arboles
binarios completos equilibrados.
2. Después analizaremos el caso para cualquier m, mediante el material
opcional de los logaritmos “divide y vencerás” de la sección 10.6.
12.3 Arboles y ordenaciones
Si n es un entero positivo arbitrario, comenzamos considerando el
siguiente procedimiento. Dada una lista de n elementos que debe
ordenarse en forma ascendente, la ordenación por inserción separa en
forma recursiva la lista dada y todas las demás sublistas a la mitad (o lo
mas cercano posible a la mitad) hasta que cada sublista contenga un
solo elemento. Después, el procedimiento intercala estas sublista en
orden ascendente hasta ordenar los n elementos originales. Los
procesos de división e inserción pueden describirse mejor mediante un
par de arboles binarios completos equilibrados, como en el siguiente
ejemplo:
12.3 Arboles y ordenaciones
(Ordenación por inserción) Con la
ordenación por inserción, la figura de la
derecha ordena la lista 6, 2, 7, 3, 4, 9, 5, 1, 8.
El árbol de la parte superior de la figura
muestra la forma en que el proceso se
divide primero la lista dada en sublistas de
tamaño 1. Después se bosqueja el proceso
de inserción usando el árbol de la parte
inferior de la figura.
12.3 Arboles y ordenaciones
12.3 Arboles y ordenaciones
Lema 12.1
Sean L1 y L2 dos listas ordenadas con números ascendentes, donde L1
contiene ni elementos, i = 1, 2. Entonces L1 y L2 pueden intercalarse en una
lista ascendente L con un máximo de n1 + n2 – 1 comparaciones.

Demostración: Para intercalar las listas L1, L2 en la lista L, utilizamos el


siguiente algoritmo:
Paso 1: Hacemos L igual a la lista vacía ∅.
Paso 2: Comparamos los primeros elementos de L1 y L2. Eliminamos el menor
de ellos de su lista correspondiente y lo colocamos al final de L.
12.3 Arboles y ordenaciones
Demostración: Para intercalar las listas L1, L2 en la lista L, utilizamos el
siguiente algoritmo:

Paso 3: Para las listas actuales L1, L2 (cada vez que se ejecuta el paso 2
se modifica una de estas listas), hay dos casos.
a) Si alguna de las listas L1, L2 es vacía, entonces la otra se concatena al
final de L, lo que completa la intersección.
b) En caso contrario, regresamos al paso 2.
12.3 Arboles y ordenaciones
Cada comparación de un numero de L1 con uno de L2 hace que un
elemento se coloque al final de la lista L, por lo que no hay mas de n1 +
n2 comparaciones. Cuando una de las listas L1 o L2 es vacía, no
necesitamos mas comparaciones, por lo que el numero máximo de
comparaciones es n1 + n2 – 1.
12.3 Arboles y ordenaciones
•Para
  determinar la función de complejidad en tiempo de la ordenación
por inserción consideraremos una lista de n elementos. Por el
momento, no nos ocuparemos del problema general y supondremos
que . En el proceso de separación, primero dividimos la lista de
elementos en dos sublistas de tamaño (Estos son los vértices de nivel 1
en el árbol que representa el proceso de división). Al continuar el
proceso, cada lista sucesiva de tamaño , está en el nivel k y se divide en
dos sublistas de tamaño . En el nivel h, cada una de las sublistas
contiene elemento.
12.3 Arboles y ordenaciones
Nivel 0 (k=0)

Nivel 1 (k=1)

Nivel 2 (k=2)

Nivel 3 (k=3)

Nivel k

Nivel h = k+1
1 23 4 5 6 7 8 9 n-1 n
12.3 Arboles y ordenaciones # de listas
 

 
1 23 4 5 6 7 8 9 n-1 n
12.3 Arboles y ordenaciones
•Al  invertir el proceso, primero intercalamos las hojas en sublistas
ordenadas de tamaño 2. Estas sublistas están en el nivel y necesita
comparaciones (una por cada par). Al continuar el proceso de inserción,
en cada uno de los vértices del nivel k, , existe una sublista de tamaño ,
que se obtiene al intercalar las dos sublistas de tamaño en su hijo (en
el nivel k+1). Del lema 12.1, este intercalado requiere un máximo de
comparaciones. Cuando se llega al hijo de la raíz, existen dos sublistas
de tamaño (en el nivel 1). Para intercalar estas sublistas en la lista final
se necesitan a lo sumo comparaciones.
12.3 Arboles y ordenaciones
•En  consecuencia, para en el nivel k existen pares de vértices. En cada
uno de estos vértices hay una sublista de tamaño , por lo que se
necesitan como máximo comparaciones para intercalar cada par de los
sublistas. Con pares de vértices en el nivel k, el numero total de
comparaciones en el nivel k es cuando mucho . Cuando sumamos sobre
todos los niveles k, donde , obtenemos que el numero total de
comparaciones es:
12.3 Arboles y ordenaciones
• 
Si n = , entonces tenemos que

Donde es el termino dominante para una n grande. Así, la función de


complejidad en tiempo (para el peor de los casos) de este procedimiento
de ordenación es y , para . Por lo tanto el numero de comparaciones
necesarias para ordenar por inserción una lista de n elementos es , para
cierta constante de proporcionalidad y para toda donde es un entero
positivo en particular (grande).
12.3 Arboles y ordenaciones
•Algoritmo
  de ordenación por inserción
Paso 1: Si n = 1, entonces ya está ordenada y el proceso termina. Si n > 1,
entonces vamos al paso 2.
Paso 2: (Dividimos la lista y ordenamos las sublistas). Realizamos lo siguiente:
1) Asignamos a m el valor .
2) Asignamos a Lista 1 la sublista
Lista [1], Lista [2],…, Lista[m],
3) Asignamos a Lista 2 la sublista
Lista [m+1], Lista[m+2],…, Lista[n].
12.3 Arboles y ordenaciones
•Algoritmo
  de ordenación por inserción
4) Aplicamos el mismo algoritmo de inserción a Lista 1 (y m) y a Lista
2(y n-m).
Paso 3: Insertamos (Lista 1, Lista 2).
La función medirá la función de complejidad en tiempo (para el peor
caso) de este algoritmo, contando el numero máximo de
comparaciones necesarias para ordenar por inserción una lista de n
elementos. Para tenemos
12.3 Arboles y ordenaciones
•El  termino es el resultado del paso 2 del algoritmo de ordenación por
inserción y el sumando se sigue del paso 2 del algoritmo y del lema
12.1.
Como , la ecuación anterior proporciona las desigualdades

También observamos que por lo que En consecuencia parece que g


es una secuencia monótona creciente.
12.3 Arboles y ordenaciones
•Aunque
  para toda , el hecho de que la ordenación por burbuja sea y la
ordenación por inserción sea no implica que el segundo método sea
mas eficiente que el primero para todo . La ordenación por el método
de la burbuja requiere un menor esfuerzo de programación y tarda
menos que el ordenamiento por burbuja para valores pequeños de
(Según varios factores, como el lenguaje de programación, el
compilador y el computador). Sin embargo, conforme crece, la
razón entre los tiempos de ejecución, medidos como se va haciendo
tan grande como se quiera.
12.3 Arboles y ordenaciones
•En  consecuencia, cuando la lista de entrada aumenta su tamaño, el
algoritmo (ordenación por el método de la burbuja) tarda
significativamente mas que el algoritmo (ordenación por inserción).
12.4 Arboles ponderados y códigos prefijo
Entre los temas a los cuales se a los cuales se aplican las matemáticas
discretas, la teoría de codificación es uno de aquellos en los que las
diferentes estructuras finitas tienen un papel fundamental. Estas
estructuras nos permiten representar y transmitir información
codificada de los símbolos de un alfabeto dado. Por ejemplo, la forma
mas frecuente de codificar o representar lo caracteres en un
computador es por medio de cadenas de longitud fija, que utiliza los
símbolos 0 y 1.
12.4 Arboles ponderados y códigos prefijo
•Supongamos
  que queremos desarrollar una forma de representar las
letras del alfabeto (inglés) mediante cadenas de ceros y unos.
Existen 26 letras.
Por lo tanto, deberíamos poder codificar estos símbolos en términos de
sucesiones de cinco bits, puesto que . Sin embargo, en el idioma inglés
y cualquier otro, no todas las letras aparecen con la misma frecuencia.
En consecuencia, sería mas eficiente utilizar sucesiones binarias de
diferentes longitudes, de modo que las letras se aparición mas
frecuente (como e, i, t) se representarán mediante las sucesiones mas
cortas posibles.
12.4 Arboles ponderados y códigos prefijo
Por ejemplo, consideremos S = {a, e, n, r, t} un subconjunto del alfabeto y
representamos los elementos de S mediante sucesiones binarias
a: 01 e: 0 n: 101r: 10 t: 1
Si debemos transmitir el mensaje “ata”, se enviara una sucesión binaria 01101. Por
desgracia, esta sucesión también se transmite con los mensajes “etn”, “atet”, y
“an”.
Consideremos un segundo esquema de codificación, dado por
a: 11 e: 0 n: 1100 r: 1101 t: 10
En este caso, el lenguaje “ata” está representado por la sucesión 11110111 y no
hay posibilidades de confusión. Es mas, usaremos el árbol binario completo para
decodificar la sucesión 11110111.
12.4 Arboles ponderados y códigos prefijo
Para la primer letra:
“a” el recorrido es con la arista 1 hasta el
hijo derecho de la raíz. Continuamos para
“t”, regresamos a la raíz y avanzamos con
el hijo derecho da la raíz con la arista 1 y
después hacía el hijo izquierdo con la
arista 0, finalmente volvemos a la raíz y
repetimos el recorrido para “a”. Se tiene
un único camino simple para cada letra.
12.4 Arboles ponderados y códigos prefijo
¿Por qué funcionó bien el segundo esquema de codificación si el
primero era ambiguo?

Primer esquema
a: 01 e: 0 n: 101 r: 10 t: 1
Segundo esquema
a: 11 e: 0 n: 1100 r: 1101 t: 10
12.4 Arboles ponderados y códigos prefijo
Definición 12.7
Un conjunto P de sucesiones binarias (que representan un conjunto de
símbolos) es un código prefijo si ninguna de las sucesiones de P es
prefijo de otra sucesión de P.

En consecuencia, las sucesiones binarias 111, 0, 1100, 1101, 10 forman


un código prefijo para las letras a, e, n, r, t, respectivamente. ¿Pero de
donde surge el árbol binario completo del ejemplo anterior?
Para responder esta pregunta necesitamos el siguiente concepto.
12.4 Arboles ponderados y códigos prefijo
Definición 12.8
Si T es un árbol binario completo de altura a, entonces T es un árbol
binario total si todas las hojas de T están en el nivel a.

Ejemplo 12.16
Para el código prefijo P = {111, 0, 1100, 1101, 10}, la sucesión binaria
mas larga tiene longitud 4. Trazamos el árbol binario total etiquetado
de altura 4, como aparece en la figura siguiente:
12.4 Arboles ponderados y códigos prefijo
12.4 Arboles ponderados y códigos prefijo
Ahora veremos un método par determinar un árbol etiquetado que
modele un código prefijo, en el que se tengan en cuenta las frecuencias
de aparición de cada símbolo en el texto promedio; En otras palabras,
un código prefijo donde usemos las sucesiones mas cortas para los
símbolos mas frecuentes.
Una elegante construcción desarrollada por David A. Huffman
proporciona una técnica para la construcción de tales arboles.
El problema general de construcción de un árbol eficiente se puede
describir como sigue:
12.4 Arboles ponderados y códigos prefijo
•Sea
  un conjunto de números positivos llamados pesos, donde Si es un
árbol binario completo con hojas, asignamos estos pesos (uno a uno) a
las hojas. El resultado es un árbol binario completo para los pesos . El
peso del árbol, P(T), se define como , donde, para cada es el numero
de nivel de la hoja asignada al peso . El objetivo es asignar los pesos de
modo que P(T) sea lo mas pequeño posible. Un árbol binario completo
T’ para estos pesos es un árbol optimo siP(T’)P(T) para cualquier otro
árbol binario completo T con los mismos pesos.
12.4 Arboles ponderados y códigos prefijo
La figura siguiente muestra dos arboles binarios completos para los
pesos 3, 5, 6, 9.
Para T1;
P(T1) = (3+9+5+6)*2 = 46

Para T2;
P(T2) = (3*3)+(5*3)+(6*2)+(9*1) =
P(T2) = 45
12.4 Arboles ponderados y códigos prefijo
•La  idea subyacente en la construcción de Huffman es que a fin de
obtener un árbol optimo T para los pesos , consideremos un árbol
optimo T’ para los n – pesos . (no podemos suponer que ). En
particular, el árbol T’ se transforma en T al reemplazar la hoja con peso
por un árbol con raíz de de altura 1, con un hijo izquierdo de peso y
un hijo derecho de peso . Para ilustrar esto, si el árbol T2, de la figura
anterior es optimo para los cuatro pesos , entonces el árbol de la figura
será optimo para los cinco pesos .
Necesitamos el siguiente lema para establecer nuestras afirmaciones.
12.4 Arboles ponderados y códigos prefijo
•Lema
  12.2
Si T es un árbol optimo para los n pesos , entonces existe un árbol
optimo T’ en el que las hijas de pesos son hermanos en el nivel maximal
(en T’).

Teorema 12.8
Sea T un árbol optimo para los pesos , donde . En la hoja con peso
colocamos un árbol binario (completo) de peso 1 y asignamos los pesos
a los hijos (hojas) de esta hoja anterior. El nuevo árbol binario T1
construido de esta forma es optimo para los pesos .
12.4 Arboles ponderados y códigos prefijo
•Teorema
  12.8 (Demostración)
Sea T2 un árbol optimo para los pesos , donde las hojas
correspondientes a los pesos son hermanos. Eliminamos las hojas de
pesos y asignamos el peso a su padre (ahora una hoja). Este árbol
binario completo se denota como T3 y P(T3) = P(T2) . Además, P(T1) =
P(T) Puesto que T es optimo, P(T) < P(T3). Si P(T) < P(T3), entonces
P(T1) < P(T2), lo que contradice la elección de T2 optimo. Por lo tanto,
P(T) = P(T3) y, en consecuencia, P(T1) < P(T2). Así T1 es optimo para los
pesos
12.4 Arboles ponderados y códigos prefijo
•Observación.
  La demostración anterior partió de un árbol optimo T2
cuya existencia se basa en el hecho de que solo existe un numero finito
de formas de asignar n pesos a un árbol binario completo de n hojas.
En consecuencia, con un numero finito de asignaciones, existe al menos
una asignación para la cual P(T) es mínima. Pero el numero finito puede
ser muy grande. Esta demostración establece la existencia de un árbol
optimo para un conjunto de pesos y desarrolla una forma para
construir tal árbol. Para este árbol (de Huffman) consideramos el
siguiente algoritmo:
Dados los pesos , procedemos como sigue:
12.4 Arboles ponderados y códigos prefijo
Paso 1: Asignamos los pesos dados, uno a cada conjunto S de n vértices
asilados [Cada vértice es la raíz de un árbol binario completo (de altura 0)
con un peso asignado a él.]
Paso 2: Si |S|> 1, hacemos lo siguiente:
a) Encontramos dos arboles T, T’ en S con los dos pesos mínimos para la
raíz p, p’ respectivamente.
b) Creamos el nuevo árbol (binario completo) T* con peso de la raíz p* = p
+ p’ y con T, T’ como subárboles izquierdo y derecho, respectivamente.
c) Colocamos T* en S y eliminamos T, T’. [Cuando |S|=1, el árbol binario
completo es S es un árbol de Huffman.
12.4 Arboles ponderados y códigos prefijo
Usaremos este algoritmo para el siguiente ejemplo:
Construimos un código prefijo optimo para los sibmolos a, o, q, u, y, z
que aparecen (en una muestra dada) con frecuencia 20, 28, 4, 12, 7,
respectivamente.
12.4 Arboles ponderados y códigos prefijo

También podría gustarte