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


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

Чому в кодуванні Хаффмана не потрібен роздільник?


1
Тому що, розшифровуючи двійкове значення, ви берете фрагмент бітів «зліва направо», залежно від значення, яке відповідає первинному тексту. Як і в цьому випадку, ви бачите, що крайній лівий фрагмент (0000) відповідає E. Якби у вашому char-коді був якийсь символ зі значенням 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 кодує "e". Жодне інше кодове слово не починається з "10", тому ви можете вивести "e". І так далі.


1
Префіксні коди також широко відомі як миттєві коди (див., Наприклад, Елементи інформаційної теорії від Cover & Thomas). Я думаю, що термін Префікс-код з'являється набагато частіше, ніж код без префіксу.
Бетмен

3
Варто також згадати, що для декодування послідовності зв'язаних кодів Хаффмана, для початку слід задати правильну межу кодового слова. Якщо спробувати декодувати послідовність на неправильній межі кодового слова, процес декодування створить неправильну послідовність вихідних символів.
rwong

@rwong: Якщо код Хаффмана почне неправильно синхронізуватися, він може продовжувати виводити неправильні символи нескінченно, але будь-який час, коли він неправильно визначає довжину символу, кількість можливих неправильних станів зменшиться.
supercat

@supercat Я думаю, я б сказав це по-іншому: Якщо декодер Хаффмана спочатку встановлений на неправильній межі кодового слова і розпочне обробку, є можливість (яка може бути нульовою чи будь-якою, і може залежати як від словника, так і від вміст бітового потоку), що він може приземлитися на правильній межі кодового слова за збігом обставин у визначений час, і коли це станеться, він створить правильний результат декодування для наступних символів. Були проведені деякі дослідження властивостей (у словнику кодового слова та бітового потоку), які гарантували б цю повторну синхронізацію.
rwong

@rwong: Якщо вихідні дані були випадковими з таким розподілом, що кожний біт потоку мав би незалежну ймовірність бути одним або нулем, ймовірність залишитися поза синхронізацією більше ніж N символів занепадає в експоненціальному масштабі зі збільшенням N. Фактичні дані, швидше за все, містять шаблони, які можуть перешкоджати ресинхронізації, але на практиці малоймовірно, що помилка на початку текстового файлу розміром 100 МБ зіпсує всі 100 МБ тексту.
supercat

13

Корисно уявити це як дерево. Ви просто об’їжджаєте дерево, поки не потрапите на листовий вузол, а потім перезапустите корінь. З алгоритму кодування Хаффмана видно, що така структура створюється в процесі.

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


6
Тут важливим аспектом є те, що всі дійсні кодові слова - це листочки. Вам знадобляться роздільники, якщо у вас були символи і на внутрішніх вузлах.
MvG

3

Ні інший код, крім E, починається з 0000. Ні інший код, крім я, починається з 0001. І так далі. У крайньому випадку, жоден код, крім e, починається з 01. У вас немає таких речей, як E = 0000, space = 000, де ви не знали б, що робити, якщо знайдете три нулі.

Подивіться на ваш закодований рядок: 0000101100000 ...

Ви читаєте перший нуль. Ви знаєте, що код є одним з E, i, y, l, k, кома або пробіл. Наступний нуль означає, що це не k, кома або пробіл, а E, i, y або l. Наступний нуль означає, що це E або i. Наступний нуль означає, що це E. Коли ви знаєте, який це код, ви знаєте, що ви розібрали всі біти для цього коду.

Тоді у вас є 101100000 ... 1 означає, що у вас є e, r, s, n або a. Наступний біт - 0, тож код є e. Знову ж, ви закінчили з цим персонажем.


-2

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


3
Хіба я вже цього не говорив, лише без заплутаного рівня багатьох вкладених негативів. (І, до речі, це не те, що ми не можемо використовувати роздільник; просто те, що нам не потрібно .)
Девід Річербі,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.