Está en la página 1de 18

CODIGOS DE HUFFMAN

Definicin : La codificacin de Huffman es una


tcnica para la compresin de datos, ampliamente
usada y muy efectiva

Ejemplo : Fichero con 100.000 caracteres. Se sabe


que aparecen 6 caracteres diferentes y la frecuencia
de aparicin de cada uno de ellos es :

a b c d e f
Frecuencia 45 13 12 16 9 5
( en miles )

Cmo codificar los caracteres para comprimir el


espacio ocupado utilizando un cdigo binario ?

Solucin 1 : Cdigo de longitud fija


Para 6 caracteres se necesitan 3 bits (300000 bits)

Fija 000 001 010 011 100 101

Solucin 2 : Cdigo de longitud variable en el que


los ms frecuentes tienen el cdigo ms corto.
Restriccin : ningn cdigo es prefijo de otro.
( 224000 bits )

Variable 0 101 100 111 1101 1100

1
Esta tcnica de codificacin se denomina cdigo
prefijo.
Codificacin : Basta con concatenar el cdigo
de cada uno de los caracteres.
Ejemplo :
aabacd 001010100111 001010100111

Descodificacin : Fcil porque ningn cdigo


es prefijo de otro cdigo NO hay
ambigedad.
Ejemplo :
101011101111011100 badadcf
Es la nica posibilidad !

Un rbol binario es una forma de representar el


cdigo prefijo que simplifica el proceso de
descodificacin :

las hojas son los caracteres,

el camino de la raz a la hojas con la interpretacin


0 a la izquierda y 1 a la derecha nos da el cdigo
de cada hoja.

2
Este sera el rbol binario de la codificacin de
longitud fija:

0 100 1
86 14
0 1 0
58 28 14
0 1 0 1 0 1

a:45 b:13 c:12 d:16 e:9 f:5

Y ste el de la codificacin de longitud variable :

0 100 1
55
a:45 0 1
25 30
0 1 0 1

c:12 b:13 14 d:16


0 1

f:5 e:9

3
Dado T el rbol binario que corresponde a una
codificacin prefijo, es fcil averiguar el nmero de
bits necesarios para codificar el fichero :
Para cada carcter c diferente del alfabeto C que
aparece en el fichero,
sea f(c) la frecuencia de c en la entrada,
sea dT(c)la profundidad de la hoja c en el rbol
T, entonces el nmero de bits requeridos es :

B(T) = f(c) dT(c)


c C
B(T) nos da el coste de T.

Algoritmo Greedy
Huffman invent un algoritmo voraz que construye
una codificacin prefijo ptima.
Construye un rbol binario de cdigos de
longitud variable de manera ascendente de
modo que [MIN] B(T).

Ejemplo de funcionamiento
Fase 1. : Caracteres colocados en orden creciente de
frecuencia.

f:5 e:9 c:12 b:13 d:16 a:45

Fase 2. y posteriores : Fusionar hasta obtener un


slo rbol manteniendo la ordenacin creciente.

4
c:12 b:13 14 d:16 a:45
0 1
f:5 e:9

14 d:16 25 a:45
0 1 0 1
f:5 e:9 c:12 b:13

25 30 a:45
0 1 0 1
c:12 b:13 14 d:16
0 1
f:5 e:9

5
a:45 55
0 1
25 30
0 1 0 1
c:12 b:13 14 d:16
0 1
f:5 e:9

0 100 1

a:45 55
0 1
25 30
0 1 0 1

c:12 b:13 14 d:16


bb:1
0 1
3
f:5 e:9

6
Implementacin del algoritmo
Se usa una cola de prioridad, Q, con clave la
frecuencia lo que permite seleccionar los dos objetos
de la cola con la frecuencia ms baja.
El resultado de fusionar dos objetos es un nuevo
objeto cuya frecuencia es la suma de frecuencias de
los dos objetos fusionados.

funcin COD_HUF ( C es conj_<car,frec> )


{ Pre : C est bien construido y no es vacio }
n := C ;
CO:= ordenar_crec_por_frec(C) ;
/* se ordena crecientemente por frecuencia el
conjunto de caracteres de la entrada */
Q := Insertar_todos (CO);
/* la cola contiene todos los elementos */
Para i=1 hasta n-1 hacer
z:= crear_objeto();
/* eleccin de los candidatos */
x := izq(z) := primero(Q); Q:= avanzar(Q);
y:= der(z) := primero(Q); Q:= avanzar(Q);
frec[z] := frec[x] + frec[y];
/* actualizar solucin */
Q:= insertar_ordenado ( Q, z);
fpara
{ Post : Q contiene un nico elemento que es un
rbol de codificacin de prefijo ptimo }
dev ( primero(Q))
ffuncin

7
Demostracin de optimalidad del criterio
Sea T un rbol binario de codificacin ptimo.
Sean b y c dos hojas hermanas en T que se
encuentran a profundidad mxima.
Sean x e y dos hojas de T tales que son los 2
caracteres del alfabeto C con la frecuencia ms
baja.

rbol T

b c

Vamos a ver que T, que es un rbol ptimo, se puede


transformar en otro rbol T, tambin ptimo, en el
que los 2 caracteres, x e y, con la frecuencia ms
baja sern hojas hermanas que estarn a la mxima
profundidad El rbol que genera el algoritmo
voraz cumple exactamente esa condicin.

8
Podemos suponer que f[b] f[c] y que f[x] f[y].
Adems, se puede deducir que f[x] f[b] y f[y]
f[c].
Se puede construir un nuevo rbol, T, en el que se
intercambia la posicin que ocupan en T las hojas b
y x.

rbol T

x c

B(T) B(T) = f[c].dT(c) f[c].dT(c) =


cC cC

= f[x].dT(x) + f[b].dT(b)
f[x].dT(x) f[b].dT(b) =

= f[x].dT(x) + f[b].dT(b)

9
f[x].dT (b) f[b].dT (x) =

= ( f[b] f[x] ) . ( dT(b) dT (x) ) 0

De forma similar, se construye el rbol T


intercambiando c e y.

rbol T
b

x y

Con este intercambio tampoco se incrementa el coste


y B(T) B(T) 0.
Por tanto, B(T) B(T) y como T es ptimo,
entonces T tambin lo es y B(T) = B(T).

Y ya para acabar la demostracin :

10
Sea T un rbol binario que representa un cdigo
prefijo ptimo para un alfabeto C. Consideremos 2
hojas hermanas, x e y, de T y sea z el padre de
ambas. Consideremos que la frecuencia de z es f[z]
= f[x] + f[y].

Entonces, el rbol T = T{x,y} representa un cdigo


prefijo ptimo para el alfabeto C = C {x, y} {z}.

Precisamente eso es lo que hace el algoritmo voraz :


una vez que ha fusionado los dos caracteres de
frecuencia ms baja, inserta un nuevo elemento en el
alfabeto con su frecuencia y repite el proceso de
seleccionar los dos elementos con frecuencia ms
baja ahora para un alfabeto con un elemento menos.

11
CAMINOS MINIMOS
Shortest-paths problem

Definiciones
Sea G=(V,E) un grafo dirigido y etiquetado con valores
naturales.
Se define el peso del camino p, con p=<v0,v1,v2, ...,vk>,
como la suma de los valores de las aristas que lo
componen.
k

peso(p) = valor(G,v i-1 ,vi)


i=1
Se define el camino de peso mnimo del vrtice u al v
en G, con u,v V, con la siguiente funcin :

MIN{ peso(p) : u v }
si hay camino de u a v
(u,v) =
en otro caso

El camino ms corto, camino mnimo, de u a v en G, se


define como cualquier camino p tal que peso(p) =
(u,v).

Los problemas de caminos mnimos


1/ Single_source shortest_paths problem :

12
Encontrar el camino ms corto entre un vrtice fijado,
source, y todos los vrtices restantes del grafo.

2/ Single_destination shortest_paths problem


Encontrar el camino ms corto desde todos los vrtices
a uno fijado, destination.

3/ Single_pair shortest_paths problem : Fijados dos


vrtices del grafo, source y destination, encontrar el
camino ms corto entre ellos.

4/ All_pairs shortest_paths problem : Encontrar el


camino ms corto entre los vrtices u y v, para todo par
de vrtices del grafo.

El algoritmo de Dijkstra (1959)


Resuelve el problema de encontrar el camino ms corto
entre un vrtice dado y todos los restantes del grafo.

funcin DIJKSTRA ( g es grafo; v_ini es vrtice )


dev ( D es vector[1..n] de naturales )

{ Pre : g=(V,E) es un grafo etiquetado con valores


naturales dirigido. Se supone que el grafo est
implementado en una matriz y que M[i,j] contiene el
valor de la arista que va del vrtice i al j y, si no hay
arista, contiene el valor infinito }

Para cada vV hacer D[v] := M[v_ini, v] fpara;


13
D[v_ini]:= 0;
VISTOS := aadir( conjunto_vacio, v_ini );
{ Inv : u : u V VISTOS: D[u] contiene la longitud
del camino ms corto desde v_ini a u que no sale de
VISTOS, es decir, el camino est formado por v_ini y
una serie de vrtices todos ellos pertenecientes a
VISTOS excepto el propio u.
u : u VISTOS: D[u] contiene la longitud del
camino ms corto desde v_ini a u }

*[ |VISTOS| < |V| --->


u := MINIMO( D, uVVISTOS );
/* el candidato es el vrtice uV-VISTOS que
tiene D mnima */
VISTOS := VISTOS {u};
Para cada v suc(g,u) t.q. v VVISTOS hacer
/* Ajustar D : Recalcular los valores para
aplicar la funcin de seleccin sobre los
candidatos que quedan */
[ D[v] > D[u] + valor( g,u,v ) --->
D[v] := D[u] + valor( g,u,v );
[] D[v] D[u] + valor ( g,u,v ) ---> seguir
]
fpara;
]
{ Post : u : uV: D[u] contiene la longitud del
camino ms corto desde v_ini a u que no sale de
VISTOS, y como VISTOS ya contiene todos los vrtices,
se tienen en D las distancias mnimas definitivas }

14
dev ( D )
ffuncin

Coste

Grafo implementado en matriz (n2):


El bucle que inicializa el vector D cuesta (n).
El bucle principal efecta n-1 iteraciones.
Coste de cada iteracin : la obtencin del mnimo,
coste lineal, y el ajuste de D que tambin es (n).

Grafo implementado con listas + Heap de mnimos


((n+|E|).log n) :
La construccin del Heap (n.log n),
Seleccionar el mnimo cuesta (1),
Cada operacin de ajuste requerir (log n).
En total se efectuan (|E) operaciones de ajustar D.

Demostracin:
Sea u un vrtice tal que uVVISTOS.
Supongamos que D[u] contiene informacin cierta, es
decir, contiene la distancia mnima entre el vrtice
inicial y u siguiendo por un camino que slo contiene
vrtices que pertenecen a VISTOS.
Si u es el vrtice con el valor de D ms pequeo, el
criterio de seleccin lo elegir como candidato e
inmediatamente pasar a formar parte de VISTOS y

15
se considerar que su D[u] es una distancia
definitiva.

Supongamos que no es CIERTO, es decir, que existe un


camino ms corto, an no considerado, desde el vrtice
inicial a u que pasa por v, obviamente vVVISTOS.
Si v se encuentra en el camino ms corto desde el
vrtice inicial a u, es que D[v]<D[u] ! lo que
contradice la eleccin de u.

siempre que D contenga informacin correcta, la


funcin de seleccin elige un vrtice con un valor de D
ya definitivo (ninguno de los vrtices que no estn en
VISTOS lograrn que se reduzca ).

Ejemplo de funcionamiento

0 2 1 1
5 1
1 4
2 2 2 1
6
3 5

Vrtice inicial : vrtice con etiqueta 0.

D: 0 1 2 3 4 5 VISTOS
0 2 5 2 {0}
0 2 3 2 3 {0,1}
0 2 3 2 3 8 {0,1,3}

16
0 2 3 2 3 5 {0,1,3,2}
0 2 3 2 3 4 {0,1,3,2,4}
0 2 3 2 3 4 {0,1,3, 2,4,5}

RECONSTRUCCION DE CAMINOS MINIMOS


En primer lugar hay que almacenar informacin para
saber que vrtices forman parte del camino de
longitud mnima que parte del vrtice inicial.

funcin DIJKSTRA_CAM ( g es grafo;


v_ini es vrtice )
dev ( D, CAMINO es vector[1..n] de natural )
{ Pre : la misma que DIJKSTRA }
Para cada vV hacer
D[v] := M[v_ini, v]; CAMINO[v]:= v_ini;
fpara;
D[v_ini]:= 0;
VISTOS := aadir( conjunto_vacio, v_ini );
*[ |VISTOS| < |V| --->
u := MINIMO( D, uVVISTOS );
VISTOS := VISTOS{u};
Para cada v suc(g,u) t.q. v VVISTOS hacer
[ D[v] > D[u] + valor( g,u,v ) --->
D[v] := D[u] + valor( g,u,v );
CAMINO[v]:= u;
[] D[v] D[u] + valor ( g,u,v ) ---> seguir
]
fpara;

17
]
{ Post : La misma de Dijkstra y u : uV: CAMINO[u]
contiene el otro vrtice de la ltima arista del camino
mnimo de v_ini a u}
dev ( D, CAMINO )
ffuncin

En segundo lugar utilizar un procedimiento recursivo,


RECONSTRUIR, que recibe el vrtice para el cual
se quiere reconstruir el camino, v, y el vector
CAMINO.

funcin RECONSTRUIR ( v, v_ini es vrtice;


CAMINO es vector[1..n] de vrtices )
dev ( s es secuencia_aristas )

[ v = v_ini ---> s := secuencia_vacia;


[] v v_ini --->
u := CAMINO[v];
s := RECONSTRUIR( u,v_ini,CAMINO);
s := concatenar( s, (u, v) );
]
{ Post : s contiene las aristas del camino mnimo desde
v_ini a v }
dev ( s )
ffuncin

18

También podría gustarte