Trabalho Estrutura De Dados Algoritmos De CompactaçãO
1. Universidade Católica de Pelotas
Centro Politécnico
Disciplina de Estrutura de Dados
Algoritmos de Compactação de Dados
Codificação Huffman e LZW
Componentes: Guilherme Cunha e Mateus Pereira
2. Codificação Huffman
Os códigos de Huffman são códigos binários
(atribuídos, por exemplo, a caracteres em um texto) de
comprimentos variados que são determinados a partir
da frequência de uso de um determinado caracter.
A idéia central é associar números binários com
menos bits aos caracteres mais usados num texto,
possibilitando a sua compactação.
3. Codificação Huffman
O algoritmo de compactação usando os códigos de
Huffman consiste basicamente de três fases:
Cálculo da frequência de cada caracter no arquivo.
Execução do algoritmo de Huffman para construção de
uma árvore binária (árvore de Huffman).
Codificação propriamente dita.
4. Codificação Huffman
O algoritmo de Huffman tem por objetivo a
construção de uma árvore binária baseada na
frequência do uso destas letras de modo que as mais
frequentemente usadas apareçam mais perto da raiz.
Esta árvore binária é construída de baixo para cima
(das folhas para raiz), começando a partir das letras
menos usadas até atingir a raiz.
5. Codificação Huffman
No início do algoritmo, cada uma das letras forma
uma árvore que é composta apenas pela raiz e cujo
conteúdo é a freqüência (f) com que esta letra ocorre
no texto.
Em seguida, são escolhidas as duas árvores com as
menores freqüências associadas e elas são unidas em
uma só árvore cujo valor da raiz é a soma do valor
destas duas. Este processo é repetido até a existência
de uma única árvore.
6. Codificação Huffman
Exemplo de Árvore de Huffman:
Caracteres: FECBDA
Frequencia: 5 9 12 13 16 45 (respectivamente)
Sequência de caracteres:
FFAAFEEEAAAAEEEECCAAAAAAAAACFFCCAAAACCBBCCAAAACCCBAA
ABBBBDDAAAAAAAADDDDBBBBBBDDDDAAAAAADDDDDDAAAAEE
Dados iniciais, ordenados por frequência de ocorrência:
7. Codificação Huffman
São combinadas as duas frequências de ocorrência mais baixa
(F e E), de forma a obter uma sub-árvore de peso 14. Logo
após deve ser movido para o lugar que lhe corresponde, face ao
peso combinado de 14.
8. Codificação Huffman
Mais uma vez, devem ser combinadas as frequências com
ocorrência de valor mais baixo. São os elementos C e B, que
irão formar uma sub-árvore de peso 25. Logo após, a sub-
árvore deve ser movida para a sua nova posição.
9. Codificação Huffman
Neste passo, a sub-árvore de peso 14 e o elemento D são
combinados e formam uma nova sub-árvore de peso 30. Deve
ser movida para a sua nova posição.
10. Codificação Huffman
Agora os dois pesos mais baixos pertencem a duas sub-árvores.
A árvore de peso 25 e a árvore de peso 30 são combinadas e
formam uma nova sub-árvore de peso 55. Como o peso da
nova sub-árvore é superior ao do elemento A, a nova sub-
árvore fica "depois" do elemento A.
12. Codificação Huffman
Codificação:
Associa-se 0 as arestas da arvore de Huffman que ligam um
nó com seu filho esquerdo e 1, as arestas que ligam um nó com
seu filho direito. O código correspondente a cada letra será
formado pelo número binário associado ao caminho da raiz até
a folha correspondente.
A tabela de codificação resultante é:
A 0
C 100
B 101
F 1100
E 1101
D 111
(O resultado obtido foi: 010010111001101111)
13. Codificação Huffman
Decodificação:
Para decodificar uma mensagem obtida, basta ir utilizando cada
bit da mensagem para percorrer a árvore de Huffman desde a
raiz até alguma folha, quando se obtém o simbolo
decodificado. Volte então para a raiz e continue a percorrer a
árvore para decodificar o próximo símbolo.
14. Codificação Huffman
Algoritmo Huffman
enquanto tamanho(alfabeto) > 1:
S0 := retira_menor_probabilidade(alfabeto)
S1 := retira_menor_probabilidade(alfabeto)
X := novo_nó
X.filho0 := S0
X.filho1 := S1
X.probabilidade := S0.probabilidade + S1.probabilidade
insere(alfabeto, X)
fim enquanto
X = retira_menor_símbolo(alfabeto) # nesse ponto só existe um símbolo.
para cada folha em folhas(X):
código[folha] := percorre_da_raiz_até_a_folha(folha)
fim para
15. Codificação Huffman
A função tamanho retorna a quantidade de nós ou folhas armazenados no
nosso repositório, chamado aqui de alfabeto.
A função retira_menor_símbolo(alfabeto) retorna o nó ou folha de menor
probabilidade no nosso repositório, e remove este símbolo do repositório.
O comando novo_nó cria um novo nó vazio.
A função insere(alfabeto, X) insere o símbolo X no nosso repositório.
A função percorre_da_raiz_até_a_folha(folha) percorre a árvore binária
da raiz até a folha acumulando os valores associados com as arestas em
seu valor de retorno.
16. Codificação Huffman
Desta forma, o caractere de maior freqüência possui o código
de menor comprimento que é exatamente a meta da
compressão estatística. Assim acontece com os demais
caracteres, em ordem proporcionalmente crescente do número
de bits.
17. Lempel-Ziv
É um algoritmo de compressão de dados sem perda
da informação, criado por Abraham Lempel e Jacob
Ziv.
É utilizado para compressão de arquivos binários e
imagens, como o formato bmp, tem maior desempenho
em arquivos que possuam grupos de repetições de
caracteres.
19. Lempel-Ziv
E como funciona a compactação?
É realizada uma leitura no arquivo solicitado e
realizada a substituição de caracteres por códigos que
utilizam menos bits.
Funciona como um dicionário de caracteres, quando é
iniciado o algoritmo é verificado se este caracter já está
inserido no dicionário, caso não esteja ele é inserido e
é retornado um bit, caso ele já esteja no dicionário, é
retornado o bit referente ao caracter.
20. Lempel-Ziv
Abaixo mostrarei um simples algoritmo para entendermos
como funciona a compactação
1.No início o dicionário contém todas as raízes possíveis e P é vazio;
2.C <= próximo caracter da sequência de entrada;
3.A string P+C existe no dicionário ?
a.se sim,
i.P <= P+C;
b.se não,
i.coloque a palavra código correspondente a P na sequência codificada;
ii.adicione a string P+C ao dicionário;
iii.P <= C;
4.Existem mais caracteres na sequência de entrada ?
a.se sim,
i.volte ao passo 2;
b.se não,
ii.coloque a palavra código correspondente a P na sequência codificada;
iii.FIM.
21. Lempel-Ziv
Abaixo mostrarei um simples algoritmo para entendermos
como funciona a descompactação:
1.No início o dicionário contém todas as raízes possíveis;
2.cW <= primeira palavra código na sequência codificada (sempre é uma
raiz);
3.Coloque a string(cW) na sequência de saída;
4.pW <= cW;
5.cW <= próxima palavra código da sequência codificada;
6.A string(cW) existe no dicionário ?
a.se sim,
i.coloque a string(cW) na sequência de saída;
ii.P <= string(pW);
iii.C <= primeiro caracter da string(cW);
iv.adicione a string P+C ao dicionário;
b.se não,
i.P <= string(pW);
ii.C <= primeiro caracter da string(pW);
iii.coloque a string P+C na sequência de saída e adicione-a ao
dicionário;
7.Existem mais palavras código na sequência codificada ?
a.se sim,
i.volte ao passo 4;
b.se não,
i.FIM.