



Estude fácil! Tem muito documento disponível na Docsity
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Prepare-se para as provas
Estude fácil! Tem muito documento disponível na Docsity
Prepare-se para as provas com trabalhos de outros alunos como você, aqui na Docsity
Os melhores documentos à venda: Trabalhos de alunos formados
Prepare-se com as videoaulas e exercícios resolvidos criados a partir da grade da sua Universidade
Responda perguntas de provas passadas e avalie sua preparação.
Ganhe pontos para baixar
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Comunidade
Peça ajuda à comunidade e tire suas dúvidas relacionadas ao estudo
Descubra as melhores universidades em seu país de acordo com os usuários da Docsity
Guias grátis
Baixe gratuitamente nossos guias de estudo, métodos para diminuir a ansiedade, dicas de TCC preparadas pelos professores da Docsity
A codificação de huffman é um método de compactação de dados que utiliza as probabilidades de ocorrência de símbolos no conjunto de dados a ser compactado para determinar códigos de tamanho variável para cada símbolo. A codificação ascii é um padrão de codificação de caracteres usado por muitas linguagens de programação, onde cada caracter é codificado com o mesmo número de bits. A codificação de huffman compacta os dados usando um número menor de bits para codificar caracteres que ocorrem mais frequentemente, permitindo economizar espaço. A ideia básica da codificação de huffman é usar um menor número de bits para representar caracteres com maior frequência. Essa técnica pode ser implementada usando uma árvore binária que armazena caracteres nas folhas, e cujos caminhos da raiz até as folhas fornecem a sequência de bits que são usados para codificar os respectivos caracteres.
Tipologia: Notas de aula
1 / 6
Esta página não é visível na pré-visualização
Não perca as partes importantes!
A codificação de Huffman é um método de compactação que usa as probabilidades de ocorrência dos símbolos no conjunto de dados a ser compactado para determinar códigos de tamanho variável para cada símbolo.
ASCII e a codificação
ASCII (American Standard Code for Information Interchange) é um padrão de codificação de caracteres usado por muitas linguages de programação. Neste padrão, cada caracter é codificado com o mesmo número de bits por caracter (e.x., 8 bits). Desta maneira, há 256 (2^8 ) possíveis combinações para representar os caracteres em ASCII. Os caracteres mais comuns, como os alfanuméricos, pontuação e caracteres de controle usam apenas 7 bits. 128 (2^7 ) caracteres diferentes podem ser codificados com 7 bits. A codificação de Huffman compacta os dados usando um número menor de bits para codificar caracteres que ocorrem mais frequentemente de maneira que nem todos os caracteres precisem ser codificados com 8 bits.
Considere a string “bom esse bombom”. Usando a codificação ASCII (8 bits por character), os 16 caracteres dessa string usam 128 bits. A tabela a seguir ilustra como a codificação funciona. Char ASCII Binário b 98 0110 0010 o 111 0110 1111 m 109 0110 1101 e 101 0110 0101 s 115 0111 0011 Espaço 32 0010 0000
A string “bom esse bombom” seria escrita numericamente assim: 98 111 109 32 101 115 115 101 32 98 111 109 98 111 109. Em binário, seria assim: 0110 0010 0110 1111 0110 1101 0010 0000 0110 0101 0111 0011 0111 0011 0110 0101 0010 0000 0110 0010 0110 1111 0110 1101 0110 0010 0110 1111 0110 1101.
Considere agora que estamos utilizando uma codificação baseada em 3-bits por caracter:
Char Binário b 0 000 o 1 001 m 2 010 e 3 011 s 4 100 Espaço 5 101
A string seria numericamente escrita assim: 0 1 2 5 3 4 4 3 5 0 1 2 0 1 2 e em binário: 000 001 010 101 011 100 100 011 101 000 001 010 000 001 010.
Usando 3-bits por caracter, a string “bom esse bombom” usa um total de 48 bits ao invés de
Árvore de Codificação
Usando uma árvore binária, podemos representar todos os caracteres ASCII como folhas de uma árvore completa (ver Figuras 1 e 2). Na Figura 3, a árvore tem 8 níveis, o que significa que o caminho da raiz à folhas sempre tem 7 arcos. Arcos da esquerda são numerados com 0 enquanto arcos da direita com 1. O código ASCII para qualquer caracter/folha é obtido seguindo o caminho da raiz à folha e concatenando os 0’s e 1’s. Por exemplo “a”, que tem código ASCII 97 (1100001 em binário) é representando na árvore pelo caminho: direita- direita-esquerda-esquerda-esquerda-esquerda-direita (Figura 3).
Figure 1 - Exemplo de árvore de codificação binária
Figure 2 - Nós folhas de uma árvore binária representando caracteres ASCII
Figure 3 - Caminho de codificação ASCII para o caracter "a"
A estrutura de uma árvore pode ser usada para determinar o código de qualquer folha apenas usando a convenção 0/1 atribuída aos arcos, como descrito. Se usarmos uma árvore diferente, nós teremos uma codificação diferente.
Podemos usar esse tipo de codificação para compactação de arquivos. Para maximar a compactação, precisamos encontrar uma árvore ótima, que apresente um número mínimo de codificação por caracter. O algoritmo para encontrar essa árvore ótima é chamado de codificação de Huffman, e foi inventando por D. Huffman em 1952.
O algoritmo de Huffman
Assuma que cada caracter em um texto está associado a um peso, que é definido pelo número de vezes que o caracter aparece em um arquivo. Na string “bom esse bombom”, os caracteres “b”, “o” e “m” têm peso 3, enquando os caracteres “e”, “s” e espaço têm peso 2. Para usar o algoritmo de Huffman, é necessário calcular esses pesos (ver Dica 1).
O algoritmo de Huffman assume que uma árvore será construída a partir de um grupo de árvores. Inicialmente essas árvores têm um único nó com um caracter e o peso deste caracter. À cada iteração do algoritmo, duas árvores são juntadas criando uma nova árvore. Isso faz com que o número de árvores diminua a cada passo. Este é o algoritmo:
A Figura 4 mostra a fase inicial do algoritmo para a string “bom esse bombom”. Os nós são mostrados com o peso que representa o número de vezes o respectivo caracter aparece na string. Note que a lista está ordenada segundo os pesos dos caracteres.
Repete-se os passos acima até que sobre apenas uma árvore. A tabela de figuras a seguir demonstra o resto da execução do algoritmo passo-a-passo.
3
“b” 3
“o” 3
“m”
2
“e” 2
“s”
2
“ ” 4
“b”
3
“o” 3
“m” 2
“e” 2
“s” 2
3
“b”
3
“o” 3
“m”
2
“e” 2
“s” 2
“ ”
3
“b”
3
“o” 3
“m”
2
“e” 2
“s” 2
“ ”
6
(^4 )
9
3
“b”
3
“o” 3
“m”
2
“e” 2
“s” 2
“ ”
(^4 )
3
“b”
3
“o” 3
“m”
2
“e” 2
“s” 2
“ ”
6
(^4 )
9
15
3
“b” 3
“o” 3
“m” 2
“e” 2
“s” 2
“ ”
3
“b”
3
“o” 3
“m”
2
“e” 2
“s” 2
“ ”
6
(^4 )
9
15
A codificação de caracteres induzida pela última árvore (árvore 8) é a seguinte (considerando 0 para arcos da esquerda e 1 para arcos da direita):
Char Binário b 111 o 00 m 01 e 100 s 101 Espaço 110
Usando essa tabela de codificação, a string “bom esse bombom” ficaria assim:
111 00 01 110 100 101 101 100 110 111 00 01 111 00 01
Desta forma usamos 39 bits para codificar a string “bom esse bombom”, ao invés de 48 bits como mostramos usando a codificação de 3-bits.
Implementação da Codificação de Huffman
Há duas partes distintas na implementação: um programa que faz a compactação e um programa que faz a descompactação. Chamaremos o programa que lê de um arquivo e produz um arquivo compactado de Compactador e o programa que produz um arquivo normal a partir de um arquivo descompactado de descompactador.
Para compactar um arquivo, é necessário a tabela de compactação, como mostramos para o exemplo “bom esse bombom”. Como vimos, esta tabela é construída com uma árvore binária de compactação.
Assumindo que um número fixo de bits é escrito em um arquivo, um arquivo compactado é criado seguindo os seguintes passos:
O arquivo compactado deve conter as informações necessárias para se chegar corretamente ao arquivo original a partir do arquivo compactado. As seguintes informações são necessárias: um cabeçalho no arquivo compactado que deve conter a árvore de codificação; e alguma marca de final de arquivo para indicar que a sequencia de bits chegou ao fim. O programa descompactador deve criar a árvore de codificação que está no cabeçalho do arquivo, ler os bits e navegar na árvore até encontrar os nós folhas correspondentes àquela sequencia de bits lidos. O custo deste algoritmo de busca é proporcional à altura da ávore.
Cabeçalho do arquivo compactado
A árvore de codificação pode ser armazenada no início do arquivo compactado. Existem várias maneiras de armazenar a árvore. Para o trabalho, use a travessia de pré-ordem para escrever cada nó visitado pela travessia. Nós folha devem ser diferenciados de nós não-folhas (nós iternos). Uma maneira de fazer a diferenciação é escrever um único bit para cada nó, por exemplo 1 para nós folhas e 0 para nós não-folha. Para nós-folha, é também necessário escrever o caracter armazenado. Para nós não-folha é necessário apenas o bit indicando de que se trata de um nó não-folha.
Caracter de final da sequencia de bits
O sistema operacional não escreve dados bit a bit e sim em “pedaços” maiores (geralmente pedaços de tamanho múltiplo da arquitetura específica do SO). Desta maneira, é muito comum o sistema operacional usar um mecanismo de buffer para acumular os dados escritos e gravá-los de uma vez. Se o seu programa escreve 3 bits e depois 2 bits, todos os bits são em algum momento escritos, mas não é possível ter certeza de quando eles serão escritos. Imagine que o sistema operacional escreva em pedaços múltiplos de 8 bits, e o seu programa tente escrever 61 bits. Nesta situação, o sistema operacional completará os 61 bits com 3 bits para completar os 64 bits (múltiplo de 8). O programa descompactador deve criar algum mecanismo para desconsiderar estes bits “extra”, uma vez que eles não representam nenhuma informação.