Изменения

4409 байт добавлено ,  3 года назад
Добавил про канонические коды.
Строка 65: Строка 65:     
После перестановки операция увеличения веса узлов продолжается дальше. Следующий узел, вес которого будет увеличен алгоритмом, — это новый родитель узла, увеличение веса которого вызвало перестановку.
 
После перестановки операция увеличения веса узлов продолжается дальше. Следующий узел, вес которого будет увеличен алгоритмом, — это новый родитель узла, увеличение веса которого вызвало перестановку.
 +
 +
== Канонические коды Хаффмана ==
 +
Проблема обычного алгоритма сжатия по Хаффману — недетерминированность. Для похожих последовательностей могут получиться разные деревья, так и одно дерево без правильной сериализации может соответствовать разным последовательностям. Для избежания применяют канонические коды Хаффмана.
 +
 +
В этом алгоритме не строится дерево Хаффмана.
 +
 +
Состоит из двух этапов:
 +
{|
 +
|
 +
# Подсчёт длины кода для какого-то символа
 +
# Составление кода.
 +
|}
 +
 +
=== Подсчёт длины ===
 +
{|
 +
|
 +
# Посчитаем частоту для каждого символа
 +
# Отсортируем их в лексикографическом порядке.
 +
# В массив запишем частоту каждой буквы.
 +
# Слева приписываем массив той же длины, но с порядковыми номерами из правого массива. Левый массив получается списком указателей на элементы правой части.
 +
# В левой части делаем не [[Двоичная куча|возрастающую пирамиду]]. Но heap будет не по значению элементов массива, а по значению на ссылаемый элемент массива.
 +
# Самый левый элемент указывает на символ из правого массива с наименьшей частотой. Его можно удалить следующим образом:
 +
## Правую половину не трогаем
 +
## Первый элемент массива заменяем на самый правый элемент левого массива, якобы сдвигая границу разделения.
 +
## Проверяем условия правильности пирамиды, если что-то не так, то надо повторить «хипизацию».
 +
## Убирается первый элемент левой части массива и объединяется ранее убранным. Сумма их частот записывается в границу между левым и правым массивом.
 +
## На место удалённого элемента в левой части записывается индекс массива куда добавили сумму частот на прошлом шаге.
 +
## Из-за того объединили два элемента нужно изменить значения этих элементов массива ссылкой на родителя, куда их положили.
 +
# Повторяем, в куче слева не останется 1 элемент.
 +
# В правой части массива получились ссылки на элементы, объеднияющие 2 символа. Поэтому идём по массиву по ссылкам, инкрементируя уровень погружения.
 +
# Количество переходов по ссылкам будет длина кода Хаффмана.
 +
|}
 +
 +
=== Составление кода ===
 +
{|
 +
|
 +
# Расположим элементы в лексикографическом порядке.
 +
# Составим таблицу, состоящую из блоков, начиная с самой большой длины кода. Каждый блок будет содержать элементы с одинаковой длиной кода.
 +
# Самый первый символ таблицы кодируется нулями.
 +
# В каждом блоке символы будут находиться в лексикографическом порядке.
 +
# Коды в блоке будут иметь двоичный вид и отличаться на 1.
 +
# При переходе в следующий блок, биты кода самого последнего символа отсекаются и добавляется 1.
 +
|}
    
== Биграммная модель ==
 
== Биграммная модель ==
Анонимный участник