Anda di halaman 1dari 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 45 b 13 c 12 d 16 e 9 f 5

Frecuencia

( 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

101 100 111 1101 1100

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.

Este sera el rbol binario de la codificacin de longitud fija: 0 0 58 0 a:45 1 b:13 0 c:12 86 1 28 1 d:16 0 14 e:9 100 1 0 14 1 f:5

Y ste el de la codificacin de longitud variable : 0 100 a:45 25 0 c:12 1 b:13 0 f:5 14 1 e:9 0 1 0 55 1 30 1 d:16

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. c:12 b:13 0 f:5 14 1 e:9 d:16 a:45

14 0 f:5 1 e:9

d:16 0 c:12

25 1 b:13

a:45

25 0 c:12 1 b:13 0 f:5 0 14

30 1 d:16 1 e:9

a:45

a:45 25 0 c:12

0 1 b:13

55

1 30 0 14 1 d:16 1 e:9

0 f:5

0 a:45

100

1 0 25 55 1 30 1 b:13 0 f:5 14 1 e:9 0 1 d:16

0 c:12

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 x y 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.

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 b y 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)

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 c 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) = 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 : Encontrar el camino ms corto entre un vrtice fijado, source, y todos los vrtices restantes del grafo.
12

valor(G,v

i-1

,vi)

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; D[v_ini]:= 0; VISTOS := aadir( conjunto_vacio, v_ini );
13

{ Inv : u : u VVISTOS: 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 } dev ( D ) ffuncin
14

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 se considerar que su D[u] es una distancia definitiva.

15

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 3

2 5 6

1 1 1 1 2 2

4 1 5

Vrtice inicial : vrtice con etiqueta 0. D: 0 0 0 0 0 0 0 1 2 2 2 2 2 2 2 5 3 3 3 3 3 3 2 2 2 2 2 2 4 3 3 3 3 3 5 8 5 4 4 VISTOS {0} {0,1} {0,1,3} {0,1,3,2} {0,1,3,2,4} {0,1,3, 2,4,5}
16

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; ] { 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 )
17

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