SlideShare ist ein Scribd-Unternehmen logo
1 von 10
Downloaden Sie, um offline zu lesen
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ção
A compressão de dados é o ato de diminuir o espaço ocupado por dados num
determinado dispositivo. Essa intervenção é realizada através de diversos algoritmos de
compressão, reduzindo a quantidade de Bytes para representar um dado, sendo esse
dado uma imagem, um texto, ou um arquivo (ficheiro).
Comprimir dados destina-se também a eliminar redundâncias, baseando-se na premissa
que muitos dados contêm informações redundantes que podem ou precisam ser
eliminadas de alguma forma. Essa forma é através de uma regra, chamada de código ou
protocolo, que, quando seguida, elimina os bits redundantes de informações, de modo a
diminuir seu tamanho nos ficheiros. Um exemplo é a sequência "AAAAA" que ocupa 5
bytes, poderia ser representada pela sequência "5A", que ocupa 2 bytes, economizando
67% 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ão
processos diferentes. Compressão reduz a quantidade de bits para representar algum
dado, 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: com
perda de dados e sem perda de dados, dizemos que um método de compressão é sem
perda (lossless) se os dados obtidos após a aplicação da técnica são idênticos aos dados
originais. Estes métodos são uteis para dados que são obtidos por meios digitais, um
exemplo 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 destes
problemáticos ou totalmente inútil.
No entanto há situações em que a perda de dados é admissível, caso de sons e imagens
por exemplo poderíamos comprimi-las com perdas de alguns detalhes que num seriam
percebidos 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 aos
originais, pois “perderam” as informações irrelevantes, então dizemos que este método
de compressão é com perdas (lossy). Neste artigo abordaremos uma das técnicas de
compressão sem perdas de dados, neste caso usaremos um algoritmo desenvolvido por
David A. Huffman, apresentaremos uma breve explicação da teoria por trás do
algoritmo, mostraremos o algoritmo em si, apresentaremos a que situações o algoritmo
se aplica, e por fim implementaremos um exemplo prático usando a técnica de Huffman.

2. Teoria

A compilação de Huffman é um procedimento de compressão que usa as probabilismos
de evento dos símbolos no conjunto de dados a ser comprimido para determinar códigos
de 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 "A
Method for the Construction of Minimum-Redundancy Codes".

Uma árvore binária completa, chamada de árvore de Huffman é arquitetada
recursivamente a partir da junção dos dois símbolos de menor possibilidade, que são
então somados em símbolos secundárias e estes símbolos secundários recolocados no
conjunto de símbolos. O processo termina quando todos os símbolos foram unidos em
sí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 a
partir desse percurso.
Neste método de compressão, é atribuído menos bits a símbolos que aparecem mais
frequentemente e mais bits para símbolos que aparecem menos. Assim, o tamanho em
bits dos caracteres codificados será diferente. Codificação de Huffman é um exemplo de
técnica de codificação estatística, que diz respeito ao uso de um código curto para
representar símbolos comuns, e códigos longos para representar símbolos pouco
frequentes. Esse é o princípio do                                       --_-, e assim por
diante. 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. A
probabilidade 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 dos
quatro caracteres. Assim, necessitamos de 2000 bits para representar o arquivo. Usando
a codificação de Huffman, podemos usar quantidades de bits diferentes para representar
estes caracteres.
Usamos bit 1 para representar e, 01 para representar t, 001 para representar x e 000 para
representar 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
bits para representar x e z, desde que seus aparecimentos são mais raros, o número total
de bits necessários para o arquivo é menor que o esquema de codificação uniforme. As
regras para atribuir bits (códigos) aos símbolos é chamado um codebook. Codebooks
são normalmente expressos em tabelas: w(e)=1, w(t)=01, w(x)=001, w(z)=000.

3. Algoritmo
Para 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 cada
símbolo. Nessa árvore as folhas representam os símbolos presentes nos dados,
integrados com suas referentes probabilidades de ocorrência. Os nós mediadores
representam a soma das probabilidades de ocorrência de todos os símbolos presentes em
suas ramificações e a raiz concebe a soma da probabilidade de todos os símbolos no
conjunto de dados. O método se inicia pela junção dos dois símbolos de menor
probabilidade, que são então unidos em um nó ao qual é atribuída a soma de suas
probabilidades. 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 sua
probabilidade. O procedimento se repete até que todos os símbolos estejam unidos sob o
nó raiz.
A cada aresta da árvore é anexo um dos dígitos binários (0 ou 1). O código
correspondente a cada símbolo é então apurado percorrendo-se a árvore e anotando-se
os dígitos das arestas percorridas desde a raiz até a folha que corresponde ao símbolo
almejado.
Tabela de frequência de caracteres:
Carac Freq Cód

espaço 7     111

a      4     010

e      4     000

f      3     1101

h      2     1010

i      2     1000

m      2     0111

n      2     0010

s      2     1011

t      2     0110

l      1     11001
o      1     00110

p      1     10011

r      1     11000

u      1     00111

x      1     10010
Pseudocó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 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




4. Aplicação
A aplicação do algoritmo de Huffman serve para casos em que não se deseja a perda de
dados, portanto é bastante útil para dados que são obtidos diretamente por meios
digitais, como textos, programas de computador, planilhas eletrônicas, etc., onde a
mínima perda de dados acarreta no não funcionamento ou torna os dados
incompreensíveis. Um texto com letras trocadas por exemplo, uma planilha com valores
faltantes ou inexatos, ou um programa de computador com comandos inválidos são
coisas que não desejamos e que podem causar contratempos. Algumas imagens e sons
necessitam ser reproduzidos de forma exata, como imagens e gravações para perícias,
impressões digitais, etc.

5. Implementação
Nesta implementação procuramos apresentar o funcionamento do algoritmo de
Huffman, sendo que em nosso experimento carregamos um arquivo de texto e jogamos
no algoritmo, obtemos um resultado prático mostrando, o símbolo, a frequência dele e o
código Huffman gerado para o símbolo em questão.
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 compressao
huffman
Aqui 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 {
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++)
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();
// 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>());
}
}
Como já vimos passamos o arquivo “.txt” com a seguinte frase: testando o algoritmo de
compressao huffman
Como veremos o algoritmo dará valores maiores para os itens menos frequentes e
valores menores para os itens mais frequentes, podemos observar com a tabela gerada
na 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ão
Neste artigo abordamos a compressão de dados, mostrando uma breve introdução acerca
do assunto, apresentamos também uma das técnicas usadas para compressão sem perda
de dados, mostramos a teoria por trás desta técnica, apresentamos alguns dos casos em
que esta técnica pode ser usada e por fim apresentamos um exemplo prático do
algoritmo de compressão em questão usando um arquivo texto e submetendo ao
algoritmo 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 David
A. Huffman, mais conhecida como Huffman, foi importante fazer uma implementação
da mesma, pois vimos na prático como o algoritmo realmente funciona, observamos o
pensamento empírico por trás do algoritmo que nos dá um embasamento maior em
nossos estudos acerca de estruturas de dados e como funciona o pensamento por trás de
uma implementação.
7. Referencias
Camara, 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 2011
https://pt.wikipedia.org/wiki/Codificacao_de_Huffman, acesso em 29 de setembro de 2011
http://rosettacode.org/wiki/Huffman_coding#Java, acesso em 29 de setembro de 2011
http://javafree.uol.com.br/, acesso em 30 de setembro de 2011
http://algs4.cs.princeton.edu/55compression/Huffman.java.html, acesso em 01 de outubro de 2011

Weitere ähnliche Inhalte

Was ist angesagt?

Modelo de camadas TCP/IP
Modelo de camadas TCP/IPModelo de camadas TCP/IP
Modelo de camadas TCP/IPEvandro Júnior
 
PHP: Linguagem + Mysql + MVC + AJAX
PHP: Linguagem + Mysql + MVC + AJAX PHP: Linguagem + Mysql + MVC + AJAX
PHP: Linguagem + Mysql + MVC + AJAX Sérgio Souza Costa
 
Bastidores e cabelagem estruturada
Bastidores e cabelagem estruturadaBastidores e cabelagem estruturada
Bastidores e cabelagem estruturadabaglungekanchi
 
Sistemas Operacionais Modernos Capítulo 3 Deadlock
Sistemas Operacionais Modernos Capítulo 3 DeadlockSistemas Operacionais Modernos Capítulo 3 Deadlock
Sistemas Operacionais Modernos Capítulo 3 DeadlockWellington Oliveira
 
2009 1 - sistemas operacionais - aula 4 - threads e comunicacao entre processos
2009 1 - sistemas operacionais - aula 4 - threads e comunicacao entre processos2009 1 - sistemas operacionais - aula 4 - threads e comunicacao entre processos
2009 1 - sistemas operacionais - aula 4 - threads e comunicacao entre processosComputação Depressão
 
Introdução à computação - Aula Prática 4 - Redes de Computadores (Cabeamento ...
Introdução à computação - Aula Prática 4 - Redes de Computadores (Cabeamento ...Introdução à computação - Aula Prática 4 - Redes de Computadores (Cabeamento ...
Introdução à computação - Aula Prática 4 - Redes de Computadores (Cabeamento ...Leinylson Fontinele
 
Aula 10 - Diagrama de Sequencia.pdf
Aula 10 - Diagrama de Sequencia.pdfAula 10 - Diagrama de Sequencia.pdf
Aula 10 - Diagrama de Sequencia.pdfIvanFontainha
 
Hierarquia de memória
Hierarquia de memóriaHierarquia de memória
Hierarquia de memóriaPAULO Moreira
 
Programação orientada a objetos: herança
Programação orientada a objetos: herançaProgramação orientada a objetos: herança
Programação orientada a objetos: herançaIvan Ricarte
 
Poo1 aula 1 - java - história e introdução
Poo1   aula 1 - java -  história e introduçãoPoo1   aula 1 - java -  história e introdução
Poo1 aula 1 - java - história e introduçãoDenis Sobrenome
 
Orientação a Objetos em Python
Orientação a Objetos em PythonOrientação a Objetos em Python
Orientação a Objetos em PythonLuciano Ramalho
 

Was ist angesagt? (20)

Modelo de camadas TCP/IP
Modelo de camadas TCP/IPModelo de camadas TCP/IP
Modelo de camadas TCP/IP
 
PHP: Linguagem + Mysql + MVC + AJAX
PHP: Linguagem + Mysql + MVC + AJAX PHP: Linguagem + Mysql + MVC + AJAX
PHP: Linguagem + Mysql + MVC + AJAX
 
Bastidores e cabelagem estruturada
Bastidores e cabelagem estruturadaBastidores e cabelagem estruturada
Bastidores e cabelagem estruturada
 
SI - Comunicação
SI - ComunicaçãoSI - Comunicação
SI - Comunicação
 
POO - 21 - Java e Banco de Dados
POO - 21 - Java e Banco de DadosPOO - 21 - Java e Banco de Dados
POO - 21 - Java e Banco de Dados
 
Sistemas Operacionais Modernos Capítulo 3 Deadlock
Sistemas Operacionais Modernos Capítulo 3 DeadlockSistemas Operacionais Modernos Capítulo 3 Deadlock
Sistemas Operacionais Modernos Capítulo 3 Deadlock
 
Estrutura de dados em Java - Filas
Estrutura de dados em Java - Filas Estrutura de dados em Java - Filas
Estrutura de dados em Java - Filas
 
Semana 2: Funções e listas, variáveis
Semana  2: Funções e listas, variáveisSemana  2: Funções e listas, variáveis
Semana 2: Funções e listas, variáveis
 
2009 1 - sistemas operacionais - aula 4 - threads e comunicacao entre processos
2009 1 - sistemas operacionais - aula 4 - threads e comunicacao entre processos2009 1 - sistemas operacionais - aula 4 - threads e comunicacao entre processos
2009 1 - sistemas operacionais - aula 4 - threads e comunicacao entre processos
 
C# REST API
C# REST APIC# REST API
C# REST API
 
Arquitetura paralela
Arquitetura paralelaArquitetura paralela
Arquitetura paralela
 
Introdução à computação - Aula Prática 4 - Redes de Computadores (Cabeamento ...
Introdução à computação - Aula Prática 4 - Redes de Computadores (Cabeamento ...Introdução à computação - Aula Prática 4 - Redes de Computadores (Cabeamento ...
Introdução à computação - Aula Prática 4 - Redes de Computadores (Cabeamento ...
 
Aula 10 - Diagrama de Sequencia.pdf
Aula 10 - Diagrama de Sequencia.pdfAula 10 - Diagrama de Sequencia.pdf
Aula 10 - Diagrama de Sequencia.pdf
 
Hierarquia de memória
Hierarquia de memóriaHierarquia de memória
Hierarquia de memória
 
ArrayList Java
ArrayList JavaArrayList Java
ArrayList Java
 
Programação orientada a objetos: herança
Programação orientada a objetos: herançaProgramação orientada a objetos: herança
Programação orientada a objetos: herança
 
Oops in java
Oops in javaOops in java
Oops in java
 
Aula 4 banco de dados
Aula 4   banco de dados Aula 4   banco de dados
Aula 4 banco de dados
 
Poo1 aula 1 - java - história e introdução
Poo1   aula 1 - java -  história e introduçãoPoo1   aula 1 - java -  história e introdução
Poo1 aula 1 - java - história e introdução
 
Orientação a Objetos em Python
Orientação a Objetos em PythonOrientação a Objetos em Python
Orientação a Objetos em Python
 

Ähnlich wie Algoritmo de compressão Huffman em Java

Compactação e Compressão de Dados
Compactação e Compressão de DadosCompactação e Compressão de Dados
Compactação e Compressão de DadosDaniel Rossi
 
Trabalho Estrutura De Dados Algoritmos De CompactaçãO
Trabalho Estrutura De Dados   Algoritmos De CompactaçãOTrabalho Estrutura De Dados   Algoritmos De CompactaçãO
Trabalho Estrutura De Dados Algoritmos De CompactaçãOMateus Ramos Pereira
 
Geração TEC - Help Desk - Ambientes e Sistemas
Geração TEC - Help Desk - Ambientes e SistemasGeração TEC - Help Desk - Ambientes e Sistemas
Geração TEC - Help Desk - Ambientes e SistemasAlan Carlos
 
Resumos para Concursos - v.34 - Informática (2014)
Resumos para Concursos - v.34 - Informática (2014)Resumos para Concursos - v.34 - Informática (2014)
Resumos para Concursos - v.34 - Informática (2014)Editora Juspodivm
 
Aula 11- Algoritmos e Programação.pptx
Aula 11- Algoritmos e Programação.pptxAula 11- Algoritmos e Programação.pptx
Aula 11- Algoritmos e Programação.pptxLemosManuel
 
compressao de dados
compressao de dadoscompressao de dados
compressao de dadosmidleofmidle
 
Aula teórica e Word
Aula teórica e WordAula teórica e Word
Aula teórica e WordMicheli Wink
 
Conhecendo o computador
Conhecendo o computadorConhecendo o computador
Conhecendo o computadorcenaic
 
Algoritmos e Programação: Manipulação de strings
Algoritmos e Programação: Manipulação de stringsAlgoritmos e Programação: Manipulação de strings
Algoritmos e Programação: Manipulação de stringsAlex Camargo
 

Ähnlich wie Algoritmo de compressão Huffman em Java (20)

APDS- Apresentaçao.pptx
APDS- Apresentaçao.pptxAPDS- Apresentaçao.pptx
APDS- Apresentaçao.pptx
 
Compactação e Compressão de Dados
Compactação e Compressão de DadosCompactação e Compressão de Dados
Compactação e Compressão de Dados
 
Trabalho Estrutura De Dados Algoritmos De CompactaçãO
Trabalho Estrutura De Dados   Algoritmos De CompactaçãOTrabalho Estrutura De Dados   Algoritmos De CompactaçãO
Trabalho Estrutura De Dados Algoritmos De CompactaçãO
 
Algoritmo
AlgoritmoAlgoritmo
Algoritmo
 
Geração TEC - Help Desk - Ambientes e Sistemas
Geração TEC - Help Desk - Ambientes e SistemasGeração TEC - Help Desk - Ambientes e Sistemas
Geração TEC - Help Desk - Ambientes e Sistemas
 
Código de Huffman
Código de HuffmanCódigo de Huffman
Código de Huffman
 
Cap07
Cap07Cap07
Cap07
 
Cap07
Cap07Cap07
Cap07
 
Resumos para Concursos - v.34 - Informática (2014)
Resumos para Concursos - v.34 - Informática (2014)Resumos para Concursos - v.34 - Informática (2014)
Resumos para Concursos - v.34 - Informática (2014)
 
01 logica
01 logica01 logica
01 logica
 
Aula 11- Algoritmos e Programação.pptx
Aula 11- Algoritmos e Programação.pptxAula 11- Algoritmos e Programação.pptx
Aula 11- Algoritmos e Programação.pptx
 
compressao de dados
compressao de dadoscompressao de dados
compressao de dados
 
Aula teórica e Word
Aula teórica e WordAula teórica e Word
Aula teórica e Word
 
Python.pptx
Python.pptxPython.pptx
Python.pptx
 
COBOL
COBOLCOBOL
COBOL
 
Conhecendo o computador
Conhecendo o computadorConhecendo o computador
Conhecendo o computador
 
Compressão de dados
Compressão de dadosCompressão de dados
Compressão de dados
 
Python
PythonPython
Python
 
Aes 25
Aes 25Aes 25
Aes 25
 
Algoritmos e Programação: Manipulação de strings
Algoritmos e Programação: Manipulação de stringsAlgoritmos e Programação: Manipulação de strings
Algoritmos e Programação: Manipulação de strings
 

Mehr von UFPA

Proteção do consumidor no comércio eletrônico sob a ótica da teoria da confiança
Proteção do consumidor no comércio eletrônico sob a ótica da teoria da confiançaProteção do consumidor no comércio eletrônico sob a ótica da teoria da confiança
Proteção do consumidor no comércio eletrônico sob a ótica da teoria da confiançaUFPA
 
Relações de consumo em ambiente eletrônico
Relações de consumo em ambiente eletrônicoRelações de consumo em ambiente eletrônico
Relações de consumo em ambiente eletrônicoUFPA
 
Ferramentas de monitoramento de redes de computadors
Ferramentas de monitoramento de redes de computadorsFerramentas de monitoramento de redes de computadors
Ferramentas de monitoramento de redes de computadorsUFPA
 
Diffserv (serviços diferenciados)
Diffserv (serviços diferenciados)Diffserv (serviços diferenciados)
Diffserv (serviços diferenciados)UFPA
 
Artigo
ArtigoArtigo
ArtigoUFPA
 
Criando e aplicando modelos de redes neurais e árvores de decisão
Criando e aplicando modelos de redes neurais e árvores de decisãoCriando e aplicando modelos de redes neurais e árvores de decisão
Criando e aplicando modelos de redes neurais e árvores de decisãoUFPA
 
Trabalho de gerencia de redes.
Trabalho de gerencia de redes.Trabalho de gerencia de redes.
Trabalho de gerencia de redes.UFPA
 
Engenharia de Testes
Engenharia de TestesEngenharia de Testes
Engenharia de TestesUFPA
 
Plano Empreendedor - Concurso Santander
Plano Empreendedor - Concurso SantanderPlano Empreendedor - Concurso Santander
Plano Empreendedor - Concurso SantanderUFPA
 

Mehr von UFPA (9)

Proteção do consumidor no comércio eletrônico sob a ótica da teoria da confiança
Proteção do consumidor no comércio eletrônico sob a ótica da teoria da confiançaProteção do consumidor no comércio eletrônico sob a ótica da teoria da confiança
Proteção do consumidor no comércio eletrônico sob a ótica da teoria da confiança
 
Relações de consumo em ambiente eletrônico
Relações de consumo em ambiente eletrônicoRelações de consumo em ambiente eletrônico
Relações de consumo em ambiente eletrônico
 
Ferramentas de monitoramento de redes de computadors
Ferramentas de monitoramento de redes de computadorsFerramentas de monitoramento de redes de computadors
Ferramentas de monitoramento de redes de computadors
 
Diffserv (serviços diferenciados)
Diffserv (serviços diferenciados)Diffserv (serviços diferenciados)
Diffserv (serviços diferenciados)
 
Artigo
ArtigoArtigo
Artigo
 
Criando e aplicando modelos de redes neurais e árvores de decisão
Criando e aplicando modelos de redes neurais e árvores de decisãoCriando e aplicando modelos de redes neurais e árvores de decisão
Criando e aplicando modelos de redes neurais e árvores de decisão
 
Trabalho de gerencia de redes.
Trabalho de gerencia de redes.Trabalho de gerencia de redes.
Trabalho de gerencia de redes.
 
Engenharia de Testes
Engenharia de TestesEngenharia de Testes
Engenharia de Testes
 
Plano Empreendedor - Concurso Santander
Plano Empreendedor - Concurso SantanderPlano Empreendedor - Concurso Santander
Plano Empreendedor - Concurso Santander
 

Algoritmo de compressão Huffman em Java

  • 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ção A compressão de dados é o ato de diminuir o espaço ocupado por dados num determinado dispositivo. Essa intervenção é realizada através de diversos algoritmos de compressão, reduzindo a quantidade de Bytes para representar um dado, sendo esse dado uma imagem, um texto, ou um arquivo (ficheiro). Comprimir dados destina-se também a eliminar redundâncias, baseando-se na premissa que muitos dados contêm informações redundantes que podem ou precisam ser eliminadas de alguma forma. Essa forma é através de uma regra, chamada de código ou protocolo, que, quando seguida, elimina os bits redundantes de informações, de modo a diminuir seu tamanho nos ficheiros. Um exemplo é a sequência "AAAAA" que ocupa 5 bytes, poderia ser representada pela sequência "5A", que ocupa 2 bytes, economizando 67% 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ão processos diferentes. Compressão reduz a quantidade de bits para representar algum dado, 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: com perda de dados e sem perda de dados, dizemos que um método de compressão é sem perda (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, um exemplo 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 destes problemáticos ou totalmente inútil. No entanto há situações em que a perda de dados é admissível, caso de sons e imagens por exemplo poderíamos comprimi-las com perdas de alguns detalhes que num seriam percebidos 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 aos originais, pois “perderam” as informações irrelevantes, então dizemos que este método de compressão é com perdas (lossy). Neste artigo abordaremos uma das técnicas de compressão sem perdas de dados, neste caso usaremos um algoritmo desenvolvido por David A. Huffman, apresentaremos uma breve explicação da teoria por trás do algoritmo, mostraremos o algoritmo em si, apresentaremos a que situações o algoritmo se aplica, e por fim implementaremos um exemplo prático usando a técnica de Huffman. 2. Teoria A compilação de Huffman é um procedimento de compressão que usa as probabilismos de evento dos símbolos no conjunto de dados a ser comprimido para determinar códigos de 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 "A Method for the Construction of Minimum-Redundancy Codes". Uma árvore binária completa, chamada de árvore de Huffman é arquitetada recursivamente a partir da junção dos dois símbolos de menor possibilidade, que são então somados em símbolos secundárias e estes símbolos secundários recolocados no conjunto de símbolos. O processo termina quando todos os símbolos foram unidos em sí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 a partir desse percurso. Neste método de compressão, é atribuído menos bits a símbolos que aparecem mais frequentemente e mais bits para símbolos que aparecem menos. Assim, o tamanho em bits dos caracteres codificados será diferente. Codificação de Huffman é um exemplo de técnica de codificação estatística, que diz respeito ao uso de um código curto para representar símbolos comuns, e códigos longos para representar símbolos pouco frequentes. Esse é o princípio do --_-, e assim por diante. 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. A probabilidade 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 dos quatro caracteres. Assim, necessitamos de 2000 bits para representar o arquivo. Usando a codificação de Huffman, podemos usar quantidades de bits diferentes para representar estes caracteres. Usamos bit 1 para representar e, 01 para representar t, 001 para representar x e 000 para representar 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 total de bits necessários para o arquivo é menor que o esquema de codificação uniforme. As regras para atribuir bits (códigos) aos símbolos é chamado um codebook. Codebooks são normalmente expressos em tabelas: w(e)=1, w(t)=01, w(x)=001, w(z)=000. 3. Algoritmo Para 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 cada símbolo. Nessa árvore as folhas representam os símbolos presentes nos dados, integrados com suas referentes probabilidades de ocorrência. Os nós mediadores representam a soma das probabilidades de ocorrência de todos os símbolos presentes em suas ramificações e a raiz concebe a soma da probabilidade de todos os símbolos no conjunto de dados. O método se inicia pela junção dos dois símbolos de menor probabilidade, que são então unidos em um nó ao qual é atribuída a soma de suas probabilidades. 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 sua probabilidade. O procedimento se repete até que todos os símbolos estejam unidos sob o nó raiz. A cada aresta da árvore é anexo um dos dígitos binários (0 ou 1). O código correspondente a cada símbolo é então apurado percorrendo-se a árvore e anotando-se os dígitos das arestas percorridas desde a raiz até a folha que corresponde ao símbolo almejado. Tabela de frequência de caracteres: Carac Freq Cód espaço 7 111 a 4 010 e 4 000 f 3 1101 h 2 1010 i 2 1000 m 2 0111 n 2 0010 s 2 1011 t 2 0110 l 1 11001
  • 4. o 1 00110 p 1 10011 r 1 11000 u 1 00111 x 1 10010 Pseudocó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 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 4. Aplicação A aplicação do algoritmo de Huffman serve para casos em que não se deseja a perda de dados, portanto é bastante útil para dados que são obtidos diretamente por meios digitais, como textos, programas de computador, planilhas eletrônicas, etc., onde a mínima perda de dados acarreta no não funcionamento ou torna os dados incompreensíveis. Um texto com letras trocadas por exemplo, uma planilha com valores faltantes ou inexatos, ou um programa de computador com comandos inválidos são coisas que não desejamos e que podem causar contratempos. Algumas imagens e sons necessitam ser reproduzidos de forma exata, como imagens e gravações para perícias, impressões digitais, etc. 5. Implementação Nesta implementação procuramos apresentar o funcionamento do algoritmo de Huffman, sendo que em nosso experimento carregamos um arquivo de texto e jogamos no algoritmo, obtemos um resultado prático mostrando, o símbolo, a frequência dele e o có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 compressao huffman Aqui 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 de compressao huffman Como veremos o algoritmo dará valores maiores para os itens menos frequentes e valores menores para os itens mais frequentes, podemos observar com a tabela gerada na 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ão Neste artigo abordamos a compressão de dados, mostrando uma breve introdução acerca do assunto, apresentamos também uma das técnicas usadas para compressão sem perda de dados, mostramos a teoria por trás desta técnica, apresentamos alguns dos casos em que esta técnica pode ser usada e por fim apresentamos um exemplo prático do algoritmo de compressão em questão usando um arquivo texto e submetendo ao algoritmo 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 David A. Huffman, mais conhecida como Huffman, foi importante fazer uma implementação da mesma, pois vimos na prático como o algoritmo realmente funciona, observamos o pensamento empírico por trás do algoritmo que nos dá um embasamento maior em nossos estudos acerca de estruturas de dados e como funciona o pensamento por trás de uma implementação.
  • 10. 7. Referencias Camara, 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 2011 https://pt.wikipedia.org/wiki/Codificacao_de_Huffman, acesso em 29 de setembro de 2011 http://rosettacode.org/wiki/Huffman_coding#Java, acesso em 29 de setembro de 2011 http://javafree.uol.com.br/, acesso em 30 de setembro de 2011 http://algs4.cs.princeton.edu/55compression/Huffman.java.html, acesso em 01 de outubro de 2011