Método de compressão de Huffman
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

Método de compressão de Huffman

on

  • 6,477 views

Este artigo trabalha com um dos tipos de algoritmos de compressão de dados. Foi usado o algoritmo de Huffman neste artigo.

Este artigo trabalha com um dos tipos de algoritmos de compressão de dados. Foi usado o algoritmo de Huffman neste artigo.

Statistics

Views

Total Views
6,477
Views on SlideShare
6,477
Embed Views
0

Actions

Likes
2
Downloads
198
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Método de compressão de Huffman Document Transcript

  • 1. Algoritmo de compressão Huffman Danilo Dias1 1 Sistemas de Informação – Universidade Federal do Oeste do Pará (UFOPA) Santarém – PA – Brasil danilohdds@gmail.com Abstract. This article expounding on data compression, in which case the techniques apply a lossless compression of data, the technique in question is to present David A. Huffman. This article in question, we present a brief introduction to compression of data showing an example of compression occurs in a practical example using the technique of Huffman compression algorithm. Resumo. Este artigo disserta acerca de compressão de dados, sendo que neste caso aplicaremos uma das técnicas de compressão sem perdas de dados, a técnica em questão que apresentaremos é a de David A. Huffman. Neste artigo em questão procuramos apresentar uma breve introdução a compressão de dados mostrando um exemplo de como ocorre a compressão em um exemplo prático usando a técnica de compressão do algoritmo de Huffman.1. IntroduçãoA compressão de dados é o ato de diminuir o espaço ocupado por dados numdeterminado dispositivo. Essa intervenção é realizada através de diversos algoritmos decompressão, reduzindo a quantidade de Bytes para representar um dado, sendo essedado uma imagem, um texto, ou um arquivo (ficheiro).Comprimir dados destina-se também a eliminar redundâncias, baseando-se na premissaque muitos dados contêm informações redundantes que podem ou precisam sereliminadas de alguma forma. Essa forma é através de uma regra, chamada de código ouprotocolo, que, quando seguida, elimina os bits redundantes de informações, de modo adiminuir seu tamanho nos ficheiros. Um exemplo é a sequência "AAAAA" que ocupa 5bytes, poderia ser representada pela sequência "5A", que ocupa 2 bytes, economizando67% de espaço.Além de eliminar redundâncias, dados são comprimidos pelos mais diversos motivos.Entre os mais conhecidos estão administrar espaço em dispositivos de armazenamento,como discos rígidos, ou ganhar desempenho (diminuir tempo) em transmissões.Ainda que possam parecer sinônimos, compressão e compactação de dados sãoprocessos diferentes. Compressão reduz a quantidade de bits para representar algumdado, enquanto a compactação tem a função de unir dados que não estejam juntados.Um exemplo clássico de compactação de dados é a desfragmentação de discos rígidos.Existem várias formas de classificar compressão de dados, os mais comuns são: comperda de dados e sem perda de dados, dizemos que um método de compressão é semperda (lossless) se os dados obtidos após a aplicação da técnica são idênticos aos dados
  • 2. originais. Estes métodos são uteis para dados que são obtidos por meios digitais, umexemplo desses tipos de dados são: planilhas eletrônicas, programas, textos entre outros,onde a perda de uma das partes desses dados torna o funcionamento final destesproblemáticos ou totalmente inútil.No entanto há situações em que a perda de dados é admissível, caso de sons e imagenspor exemplo poderíamos comprimi-las com perdas de alguns detalhes que num seriampercebidos pelos olhos e ouvidos humanos, nestes casos a perda de dados é aceitável,portanto nestes casos os dados obtidos após a compressão não são idênticos aosoriginais, pois “perderam” as informações irrelevantes, então dizemos que este métodode compressão é com perdas (lossy). Neste artigo abordaremos uma das técnicas decompressão sem perdas de dados, neste caso usaremos um algoritmo desenvolvido porDavid A. Huffman, apresentaremos uma breve explicação da teoria por trás doalgoritmo, mostraremos o algoritmo em si, apresentaremos a que situações o algoritmose aplica, e por fim implementaremos um exemplo prático usando a técnica de Huffman.2. TeoriaA compilação de Huffman é um procedimento de compressão que usa as probabilismosde evento dos símbolos no conjunto de dados a ser comprimido para determinar códigosde tamanho variável para cada símbolo. Foi desenvolvido em 1952 por David A.Huffman que na época era estudante de doutorado no MIT, foi publicado no artigo "AMethod for the Construction of Minimum-Redundancy Codes".Uma árvore binária completa, chamada de árvore de Huffman é arquitetadarecursivamente a partir da junção dos dois símbolos de menor possibilidade, que sãoentão somados em símbolos secundárias e estes símbolos secundários recolocados noconjunto de símbolos. O processo termina quando todos os símbolos foram unidos emsímbolos auxiliares, formando uma árvore binária. A árvore é então percorrida,atribuindo-se valores binários de 1 ou 0 para cada aresta, e os códigos são gerados apartir desse percurso.Neste método de compressão, é atribuído menos bits a símbolos que aparecem maisfrequentemente e mais bits para símbolos que aparecem menos. Assim, o tamanho embits dos caracteres codificados será diferente. Codificação de Huffman é um exemplo detécnica de codificação estatística, que diz respeito ao uso de um código curto pararepresentar símbolos comuns, e códigos longos para representar símbolos poucofrequentes. Esse é o princípio do --_-, e assim pordiante. Usaremos um exemplo para mostrar como a codificação de Huffman funciona.Suponha que temos um arquivo contendo 1000 caracteres, que são e, t, x e z. Aprobabilidade de ocorrência de e, t, x, e z são 0.8, 0.16, 0.02, e 0.02 respectivamente.Em um método de codificação normal, necessitamos 2 bits para representar cada um dosquatro caracteres. Assim, necessitamos de 2000 bits para representar o arquivo. Usandoa codificação de Huffman, podemos usar quantidades de bits diferentes para representarestes caracteres.Usamos bit 1 para representar e, 01 para representar t, 001 para representar x e 000 pararepresentar z. Neste caso, o número total de bits necessários para representar o arquivo é1000*(1*0.8+2*0.16+3*0.02+3*0.02)=1240. Assim, embora tenhamos utilizado mais
  • 3. bits para representar x e z, desde que seus aparecimentos são mais raros, o número totalde bits necessários para o arquivo é menor que o esquema de codificação uniforme. Asregras para atribuir bits (códigos) aos símbolos é chamado um codebook. Codebookssão normalmente expressos em tabelas: w(e)=1, w(t)=01, w(x)=001, w(z)=000.3. AlgoritmoPara conferir modos mais frequentes aos códigos binários de menor comprimento,constrói-se uma árvore binária fundamentada nas probabilidades de ocorrência de cadasímbolo. Nessa árvore as folhas representam os símbolos presentes nos dados,integrados com suas referentes probabilidades de ocorrência. Os nós mediadoresrepresentam a soma das probabilidades de ocorrência de todos os símbolos presentes emsuas ramificações e a raiz concebe a soma da probabilidade de todos os símbolos noconjunto de dados. O método se inicia pela junção dos dois símbolos de menorprobabilidade, que são então unidos em um nó ao qual é atribuída a soma de suasprobabilidades. Este novo nó é então tratado como se fosse uma folha da árvore, isto é,um dos símbolos do alfabeto, e comparado com os demais de acordo com suaprobabilidade. O procedimento se repete até que todos os símbolos estejam unidos sob onó raiz.A cada aresta da árvore é anexo um dos dígitos binários (0 ou 1). O códigocorrespondente a cada símbolo é então apurado percorrendo-se a árvore e anotando-seos dígitos das arestas percorridas desde a raiz até a folha que corresponde ao símboloalmejado.Tabela de frequência de caracteres:Carac Freq Códespaço 7 111a 4 010e 4 000f 3 1101h 2 1010i 2 1000m 2 0111n 2 0010s 2 1011t 2 0110l 1 11001
  • 4. o 1 00110p 1 10011r 1 11000u 1 00111x 1 10010Pseudocódigo para a construção da árvore: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 enquantoX = 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 para4. AplicaçãoA aplicação do algoritmo de Huffman serve para casos em que não se deseja a perda dedados, portanto é bastante útil para dados que são obtidos diretamente por meiosdigitais, como textos, programas de computador, planilhas eletrônicas, etc., onde amínima perda de dados acarreta no não funcionamento ou torna os dadosincompreensíveis. Um texto com letras trocadas por exemplo, uma planilha com valoresfaltantes ou inexatos, ou um programa de computador com comandos inválidos sãocoisas que não desejamos e que podem causar contratempos. Algumas imagens e sonsnecessitam ser reproduzidos de forma exata, como imagens e gravações para perícias,impressões digitais, etc.5. ImplementaçãoNesta implementação procuramos apresentar o funcionamento do algoritmo deHuffman, sendo que em nosso experimento carregamos um arquivo de texto e jogamosno algoritmo, obtemos um resultado prático mostrando, o símbolo, a frequência dele e ocódigo Huffman gerado para o símbolo em questão.
  • 5. A primeira parte do experimento geramos o arquivo “.txt” e armazenamos no disco“c:/”, o arquivo tem gravado a seguinte frase: testando o algoritmo de compressaohuffmanAqui temos o algoritmo de Huffman em java:/** To change this template, choose Tools | Templates* and open the template in the editor.*/package Huffman.code;/**** @author Danilo*/abstract class HuffmanTree implements Comparable<HuffmanTree> { public int frequency; // the frequency of this tree public HuffmanTree(int freq) { frequency = freq; } public int compareTo(HuffmanTree tree) { return frequency - tree.frequency; }}class HuffmanLeaf extends HuffmanTree { public char value; // the character this leaf represents public HuffmanLeaf(int freq, char val) { super(freq); value = val; }}class HuffmanNode extends HuffmanTree {
  • 6. public HuffmanTree left, right; public HuffmanNode(HuffmanTree l, HuffmanTree r) { super(l.frequency + r.frequency); left = l; right = r; }}package Huffman.code;import java.io.BufferedInputStream;import java.io.DataInputStream;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.util.PriorityQueue;import java.util.Stack;import java.util.logging.Level;import java.util.logging.Logger;/**** @author Danilo*/public class HuffmanCode{ // input is an array of frequencies, indexed by character code public static HuffmanTree buildTree(int[] charFreqs){ PriorityQueue<HuffmanTree> trees = new PriorityQueue<HuffmanTree>(); // initially, we have a forest of leaves // one for each non-empty character for (int i = 0; i < charFreqs.length; i++)
  • 7. if (charFreqs[i] > 0) trees.offer(new HuffmanLeaf(charFreqs[i], (char)i)); assert trees.size() > 0; // loop until there is only one tree left while (trees.size() > 1) { // two trees with least frequency HuffmanTree a = trees.poll(); HuffmanTree b = trees.poll(); // put into new node and re-insert into queue trees.offer(new HuffmanNode(a, b)); } return trees.poll();}public static void printCodes(HuffmanTree tree, Stack<Character> prefix) { assert tree != null; if (tree instanceof HuffmanLeaf) { HuffmanLeaf leaf = (HuffmanLeaf)tree; // print out character and frequency System.out.print(leaf.value + "t" + leaf.frequency + "t"); // print out code for this leaf, which is just the prefix for (char bit : prefix) System.out.print(bit); System.out.println(); } else if (tree instanceof HuffmanNode) { HuffmanNode node = (HuffmanNode)tree; // traverse left prefix.push(0); printCodes(node.left, prefix); prefix.pop();
  • 8. // traverse right prefix.push(1); printCodes(node.right, prefix); prefix.pop(); } } public static void main(String[] args) throws IOException { String arquivo = "C:/teste.txt"; FileInputStream fis = null; try { fis = new FileInputStream(arquivo); } catch (FileNotFoundException ex) { Logger.getLogger(HuffmanCode.class.getName()).log(Level.SEVERE, null,ex); } BufferedInputStream buffReader = new BufferedInputStream(fis); DataInputStream data = new DataInputStream(buffReader); byte[] b = new byte[fis.available()]; data.read(b); int[] charFreqs = new int[256]; for (char c : new String(b).toCharArray()) { charFreqs[c]++; } // build tree HuffmanTree tree = buildTree(charFreqs); // print out results System.out.println("SYMBOLtWEIGHTtHUFFMAN CODE"); printCodes(tree, new Stack<Character>());
  • 9. }}Como já vimos passamos o arquivo “.txt” com a seguinte frase: testando o algoritmo decompressao huffmanComo veremos o algoritmo dará valores maiores para os itens menos frequentes evalores menores para os itens mais frequentes, podemos observar com a tabela geradana saída da execução de nosso algoritmo: 1) Os símbolos usados em nosso arquivo, contando com os espaços. 2) A frequência desses símbolos, por exemplo, temos um peso 3 para o caractere “m”, pois ele repete três vezes, procurando assim representar os 3 elementos com a menor quantidade de bits possíveis. 3) Por fim podemos observar o código Huffman para cada elemento de acordo com a sua frequência, ou seja, valores maiores para itens mais frequentes e menores para itens menos frequentes.6. ConclusãoNeste artigo abordamos a compressão de dados, mostrando uma breve introdução acercado assunto, apresentamos também uma das técnicas usadas para compressão sem perdade dados, mostramos a teoria por trás desta técnica, apresentamos alguns dos casos emque esta técnica pode ser usada e por fim apresentamos um exemplo prático doalgoritmo de compressão em questão usando um arquivo texto e submetendo aoalgoritmo de Huffman e realizando uma breve analise em cima do resultado obtido.Portanto, vimos a aplicação de uma das técnicas de compressão, neste caso a de DavidA. Huffman, mais conhecida como Huffman, foi importante fazer uma implementaçãoda mesma, pois vimos na prático como o algoritmo realmente funciona, observamos opensamento empírico por trás do algoritmo que nos dá um embasamento maior emnossos estudos acerca de estruturas de dados e como funciona o pensamento por trás deuma implementação.
  • 10. 7. ReferenciasCamara, Marco. Criptografia e compressão de dados. UCSAL – Universidade Católica de Salvador.https://pt.wikipedia.org/wiki/Compressao_de_dados, acesso em 29 de setembro de 2011https://pt.wikipedia.org/wiki/Codificacao_de_Huffman, acesso em 29 de setembro de 2011http://rosettacode.org/wiki/Huffman_coding#Java, acesso em 29 de setembro de 2011http://javafree.uol.com.br/, acesso em 30 de setembro de 2011http://algs4.cs.princeton.edu/55compression/Huffman.java.html, acesso em 01 de outubro de 2011