Кодирование Хаффмана: почему не нужен разделитель?

17
Char        Code
====        ====
E           0000
i           0001
y           0010
l           0011
k           0100
.           0101
space       011
e           10
r           1100
s           1101
n           1110
a           1111

Первоначальный текст:

Жуткие глаза видны возле озера

Кодирование:
0000101100000110011100010101101101001111101011111100011001111110100100101

Почему не требуется разделитель в кодировке Хаффмана?

BufBills
источник
1
Потому что когда вы декодируете двоичное значение, вы берете кусок битов «слева направо», в зависимости от того, что сначала соответствует значению из исходного текста. Как и в этом случае, вы видите, что крайний левый фрагмент (0000) соответствует E. Если бы в вашем коде был какой-либо символ со значением 000, вы бы заменили 000 на этот символ, а затем снова начали поиск по оставшимся битам в «слева направо». Вот почему вам не нужно никакого разделения.
Сайед Али Хамза
1
Вопрос подразумевает, что разделители обычно необходимы. Вы уже знаете, что вам не нужны разделители внутри Eerie eyes seen near lake(ну, кроме символа пробела). Но сами персонажи не нуждаются в разделителях. Почему не так?
MSalters
Попробуй расшифровать его самому, двусмысленности никогда не бывает.
njzk2
@MSalters: Но сепараторы имеют , как правило , требуется с переменной длиной слова: cat cheat for micecatch eat form ice. Ваша аналогия ошибочна: каждая буква атомарна; буквы тривиально различимы и неразделимы. Лучшей аналогией будет «Почему вы можете читать рукописный (рукописный) сценарий, когда каждое слово представляет собой одну длинную, извивающуюся, самопересекающуюся строку?», И даже это плохая аналогия, поскольку вы можете посмотреть на рукописное слово ( или даже часть одного) и различать отдельные буквы - тогда как строка в кодировке Хаффмана - это бред, если вы не видите начало.
G-Man говорит: «Восстановите Монику»
@MSalters Я не вижу смысла. Мне не нужны разделители для символов, потому что мы используем кодировку с фиксированной шириной: каждый последующий блок из восьми битов соответствует одному символу. Но кодирование Хаффмана не фиксированной ширины, поэтому вопрос.
Дэвид Ричерби

Ответы:

50

Вам не нужен разделитель, потому что коды Хаффмана - это коды без префиксов (также бесполезно известные как «префиксные коды»). Это означает, что ни одно кодовое слово не является префиксом любого другого кодового слова. Например, кодовое слово «e» в вашем примере равно 10, и вы можете видеть, что никакие другие кодовые слова не начинаются с цифр 10.

Это означает, что вы можете жадно декодировать, читая закодированную строку слева направо и выводя символ, как только увидите кодовое слово. Например, 0, 00 и 000 ничего не кодируют, поэтому вы продолжаете читать биты. Когда вы читаете 0000, это кодирует «E» и, поскольку в коде нет префиксов, вы знаете, что другого кодового слова 0000x нет, поэтому теперь вы можете вывести «E» и начать читать следующее кодовое слово. Опять же, 1 ничего не кодирует, но 10 кодирует «е». Никакие другие кодовые слова не начинаются с «10», поэтому вы можете вывести «e». И так далее.

Дэвид Ричерби
источник
1
Префиксные коды также широко известны как «Мгновенные коды» (см., Например, «Элементы теории информации» от Cover & Thomas). Я думаю, что термин код префикса встречается гораздо чаще, чем код без префиксов.
Бэтмен
3
Стоит также упомянуть, что для декодирования последовательности сцепленных кодов Хаффмана для начала необходимо указать правильную границу кодового слова. Если попытаться декодировать последовательность на неправильной границе кодового слова, процесс декодирования сгенерирует неправильную последовательность выходных символов.
Rwong
@ rwong: Если код Хаффмана начинает некорректно синхронизироваться, он может продолжать выводить неправильные символы бесконечно, но каждый раз, когда он неправильно определяет длину символа, число возможных неправильных состояний будет уменьшено.
суперкат
@supercat Я думаю, я бы сформулировал это по-другому: если декодер Хаффмана изначально установлен на неправильной границе кодового слова и начинает обработку, существует вероятность (которая может быть нулевой или любой, и может зависеть как от словаря, так и от содержимое битового потока), что он может попасть на правильную границу кодового слова по совпадению за конечное время, и когда это произойдет, он даст правильный результат декодирования для последующих символов. Было проведено некоторое исследование свойств (в словаре кодовых слов и в потоке битов), которые гарантировали бы эту повторную синхронизацию.
Rwong
@ rwong: если исходные данные были случайными с таким распределением, что каждый бит потока имел бы независимую вероятность того, что он равен единице или нулю, вероятность остаться не синхронизированной для более чем N символов будет экспоненциально уменьшаться с увеличением N. Фактические данные с большей вероятностью содержат шаблоны, которые могут помешать повторной синхронизации, но на практике маловероятно, что ошибка в начале текстового файла размером 100 МБ повредит все 100 МБ текста.
суперкат
13

Полезно представить это как дерево. Вы просто пересекаете дерево, пока не дойдете до листового узла, а затем перезапустите его из корня. Из алгоритма, который выполняет кодирование Хаффмана, вы можете видеть, что такая структура создается в процессе.

https://en.wikipedia.org/wiki/File:HuffmanCodeAlg.png

quietContest
источник
6
Важным аспектом здесь является то, что все допустимые кодовые слова являются листами. Вам понадобятся разделители, если у вас также есть символы на внутренних узлах.
MvG
3

Никакой код, кроме E, не начинается с 0000. Никакой код, кроме I, не начинается с 0001. И так далее. В крайнем случае, никакой код, кроме e, не начинается с 01. У вас нет таких вещей, как E = 0000, пробел = 000, где вы не знаете, что делать, если найдете три нуля.

Посмотрите на вашу закодированную строку: 0000101100000 ...

Вы читаете первый ноль. Вы знаете, что код - это E, i, y, l, k, запятая или пробел. Следующий ноль означает, что это не k, запятая или пробел, а E, i, y или l. Следующий ноль означает, что это E или я. Следующий ноль означает, что это E. Когда вы знаете, какой это код, вы знаете, что проанализировали все биты для этого кода.

Тогда у вас есть 101100000 ... 1 означает, что у вас есть e, r, s, n или a. Следующий бит равен 0, поэтому код равен e. Опять же, вы закончили с этим персонажем.

gnasher729
источник
-2

Мы не можем использовать разделитель в кодировке Хаффмана, потому что двоичный эквивалент каждой буквы не соответствует префиксному коду любой буквы, поэтому мы можем обойтись даже без использования разделителя.

Сандип Дас
источник
3
Разве я уже не говорил этого, только без запутанных уровней многих вложенных отрицаний. (И, кстати, дело не в том, что мы не можем использовать разделитель; просто нам это не нужно .)
David Richerby