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