88 lines
5.4 KiB
Markdown
88 lines
5.4 KiB
Markdown
#алгоритмы #сжатие
|
||
|
||
> Код Хаффмана — хороший пример использования бинарных деревьев. Он также лежит в основе алгоритмов сжатия текста
|
||
|
||
```
|
||
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)]]
|
||
|
||
Источники:
|
||
- [[Адитья Бхаргава - Грокаем Алгоритмы]] |