Base/Knowledges/IT/Алгоритмы/Код Хаффмана (Huffman coding).md
2026-02-23 19:52:05 +03:00

88 lines
5.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#алгоритмы #сжатие
> Код Хаффмана — хороший пример использования бинарных деревьев. Он также лежит в основе алгоритмов сжатия текста
```
00000000: 01110100 01101001 01101100 01110100
tilt
```
В кодировке `ISO-8859-1`
|Символ | Двоичное представление | Десятичное представление |
| ----- | ---------------------- | ------------------------ |
| t | 01110100 | 116 |
| i | 01101001 | 105 |
| l | 01101100 | 108 |
Здесь в игру вступает сжатие. Для слова `tilt` не нужны все 256 возможных
букв, достаточно трех. Таким образом, для представления буквы не тре-
буется 8 бит, можно обойтись всего двумя. Можно было бы определить
собственную 2-битную кодировку для этих трех букв:
|Символ | Двоичное представление | Десятичное представление |
| ----- | ---------------------- | ------------------------ |
| t | 00 | 0 |
| i | 01 | 1 |
| l | 10 | 2 |
Хаффмана: он ищет повторяющиеся символы и использует для их представления
менее 8 бит. В результате происходит сжатие данных. Код Хаффмана генерирует дерево. Буквы помещаются только в листовых узлах. И от корня к каждому листовому узлу существует уникальный путь — это одно из свойств деревьев. Таким образом, можно гарантировать, что наложения не будет. Это свойство также гарантирует, что каждой букве соответствует только один код.
В таком случае можно записать `tilt` в новой кодировке: `00011000` (для удобства можно разделить последовательность, добавив в нее пробелы: `00 01 10 00`)
![[Pasted image 20250114092202.png]]
По этому дереву можно узнать код каждой буквы. Начиная с корневого
узла, найдите путь вниз до буквы *L*. Каждый раз, когда на этом пути выбирается левая ветвь, к коду добавляется 0, а когда выбирается правая ветвь — 1.
Когда вы доберетесь до буквы, продвижение по дереву остановится. Таким
образом, букве *L* будет соответствовать код `01`.
Дерево определяет три кода:
```
i = 00
l = 01
t = 1
```
В отличие от ISO-8859-1, в кодировке Хаффмана коды не обязательно должны иметь одинаковую длину
***
На этот раз сжатие применяется к фразе «paranoid android»
![[Pasted image 20250114092554.png]]
|Символ | Двоичное представление |
| ----- | ---------------------- |
| P | 0001 |
| O | 001 |
| A | 010 |
| R | 011 |
| D | 10 |
| I | 110 |
| N | 111 |
| '_' | 0000 |
Так как длина кода изменяется, разбить его на фрагменты невозможно, приходится перебирать цифры по одной, словно просматривая пленку с цифрами.
Длины кодов могут изменяться, поэтому декодирование должно выполняться по-другому.
Такая схема требует больших усилий по сравнению с разделением на блоки.
С другой стороны, у нее есть одно большое преимущество. Обратите вни-
мание: у букв, встречающихся чаще, коды более короткие. D встречается
в тексте три раза, поэтому ее код состоит всего из двух цифр — в отличие от
буквы I, встречающейся два раза, и буквы P, которая встречается всего один
раз. Вместо того чтобы кодировать все 4 битами, мы применяем повышен-
ное сжатие для часто используемых букв. В длинном тексте это обеспечит
большой выигрыш!
Связанные темы:
- [[Бинарное дерево (Binary tree)]]
Источники:
- [[Адитья Бхаргава - Грокаем Алгоритмы]]