Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » Теория - Алгоритм Хаффмана

Ответить
Настройки темы
Теория - Алгоритм Хаффмана

Новый участник


Сообщения: 3
Благодарности: 0

Профиль | Отправить PM | Цитировать


Изменения
Автор: eg01st
Дата: 02-11-2010
Всем привет! Поступил на факультет компьютерной инженерии, препод по проф предмету дал задачку, и пообещал поставить 5 балов за год, если услышит правильный ответ)

Итак: недавно я узнал что такое архивирование, и как оно приблизительно работает. Алгоритм Хафмана анализирует файл, анализирует в нём самые часто попадающиеся символы и кодирует их в самые мелкие битовые значения. Символы, которые попадаются реже - кодирует в более длинное битовое значение. Тот, кто знает как это работает - в курсе.

Вопрос: как этот алгоритм правильно расшифровывает весь файл, если допустим код 010001011011010101, символ "а" - 01, а символ "я" - 010001. Как он понимает что нужно преобразовывать символ "а", а не "я"?

В интернетах толкового ответа не нашел, везде только написано как он шифрует, а как расшифровывает - пара слов о префиксных кодах, которые я так и не понял.

Прошу как можно проще дать ответ на вопрос, буду благодарен)

Отправлено: 01:34, 02-11-2010

 

Ветеран


Сообщения: 27449
Благодарности: 8087

Профиль | Отправить PM | Цитировать


eg01st, описанная Вами ситуация:
Цитата eg01st:
допустим код 010001011011010101, символ "а" - 01, а символ "я" - 010001 »
невозможна в принципе. Ибо алгоритм кодирования построен таким образом, что кодовая последовательность для кодирования символа формируется таким образом, что она (кодовая последовательность) однозначно идентифицирует исходный символ.

читать дальше »
Принцип достаточно прост: минимизировать среднее количество кодовых символов, приходящихся на одну букву. Кодируемые элементы сообщения (буквы) располагаются в порядке убывания частот их появления в сообщении. Затем они разделяются на две группы таком образом, чтобы сумма вероятностей появления букв в верхней группе была примерно равна сумме вероятностей появления букв букв в нижней группе (например, в верхней группе не больше, нежели в нижней). Верхней группе приписывается символ «0», а нижней, соответственно, — «1». Эти символы обозначают первый знак кодовой последовательности.

Далее, каждая из двух групп, полученных на предыдущем этапе, в свою очередь делится на две подгруппы, каждой из которых так же присваивается очередной символ кодовой последовательности. Новые полученные символы обозначают второй знак в соответствующих кодовых последовательностях.

Процесс продолжается до тех пор, пока в каждой подгруппе не останется ровно одна буква, которая будет закодирована кодовой последовательностью полученных двоичных символов.

Например, закодируем сообщение:
Код: Выделить весь код
синий, синий иней
Начинаем с частот появления букв в исходном сообщении:
Код: Выделить весь код
«с» — 2;
«и» — 5;
«н» — 3;
«й» — 3;
« » — 3;
«,» — 1;
«е» — 1
Таким образом, общее число букв в исходном сообщении — 18 (2+5+3+3+3+1+1).

Вероятности появления букв в исходном сообщении:
Код: Выделить весь код
«с» — 2/18;
«и» — 5/18;
«н» — 3/18;
«й» — 3/18;
« » — 3/18;
«,» — 1/18;
«е» — 1/18
Располагаем буквы в таблицу в соответствии с вероятностями их появления в исходном сообщении и делаем присвоение первого двоичного символа:
Код: Выделить весь код
┌─────┬──────┬───┐
│ «и» │ 5/18 │ 0 │
│     │      │   │
│ «н» │ 3/18 │   │
│     │      ├───┤
│ «й» │ 3/18 │ 1 │
│     │      │   │
│ « » │ 3/18 │   │
│     │      │   │
│ «с» │ 2/18 │   │
│     │      │   │
│ «,» │ 1/18 │   │
│     │      │   │
│ «е» │ 1/18 │   │
└─────┴──────┴───┘
Замечание: при равной вероятности порядок следования исходных букв выбирается произвольно (в нашем случае это [«н», «й», « »] и [«,» , «е»]).

Далее, каждую половину делим опять же пополам по вероятностям:
Код: Выделить весь код
┌─────┬──────┬───┬───┐
│ «и» │ 5/18 │ 0 │ 0 │
│     │      │   ├───┤
│ «н» │ 3/18 │   │ 1 │
│     │      ├───┼───┤
│ «й» │ 3/18 │ 1 │ 0 │
│     │      │   ├───┤
│ « » │ 3/18 │   │ 1 │
│     │      │   │   │
│ «с» │ 2/18 │   │   │
│     │      │   │   │
│ «,» │ 1/18 │   │   │
│     │      │   │   │
│ «е» │ 1/18 │   │   │
└─────┴──────┴───┴───┘
Повторяем эту операцию до тех пор, пока каждая буква исходного сообщения не будет закодирована:
Код: Выделить весь код
┌─────┬──────┬───┬───┬───────────┬───────┐
│ «и» │ 5/18 │ 0 │ 0 │           │ 00    │
│     │      │   ├───┼───────────┼───────┤
│ «н» │ 3/18 │   │ 1 │           │ 01    │
│     │      ├───┼───┼───────────┼───────┤
│ «й» │ 3/18 │ 1 │ 0 │           │ 10    │
│     │      │   ├───┼───────────┼───────┤
│ « » │ 3/18 │   │ 1 │ 0         │ 110   │
│     │      │   │   ├───┬───────┼───────┤
│ «с» │ 2/18 │   │   │ 1 │ 0     │ 1110  │
│     │      │   │   │   ├───┬───┼───────┤
│ «,» │ 1/18 │   │   │   │ 1 │ 0 │ 11110 │
│     │      │   │   │   │   ├───┼───────┤
│ «е» │ 1/18 │   │   │   │   │ 1 │ 11111 │
└─────┴──────┴───┴───┴───┴───┴───┴───────┘
Таким образом, символы исходного сообщения могут быть закодированы следующими кодовыми последовательностями:
Код: Выделить весь код
«и» — «00»;
«н» — «01»;
«й» — «10»;
« » — «110»;
«с» — «1110»;
«,» — «11110»;
«е» — «11111».
Соответственно, исходное сообщение:
Код: Выделить весь код
┌─────┬───────┐
│ «с» │ 1110  │
├─────┼───────┤
│ «и» │ 00    │
├─────┼───────┤
│ «н» │ 01    │
├─────┼───────┤
│ «и» │ 00    │
├─────┼───────┤
│ «й» │ 10    │
├─────┼───────┤
│ «,» │ 11110 │
├─────┼───────┤
│ « » │ 110   │
├─────┼───────┤
│ «с» │ 1110  │
├─────┼───────┤
│ «и» │ 00    │
├─────┼───────┤
│ «н» │ 01    │
├─────┼───────┤
│ «и» │ 00    │
├─────┼───────┤
│ «й» │ 10    │
├─────┼───────┤
│ « » │ 110   │
├─────┼───────┤
│ «и» │ 00    │
├─────┼───────┤
│ «н» │ 01    │
├─────┼───────┤
│ «е» │ 11111 │
├─────┼───────┤
│ «й» │ 10    │
└─────┴───────┘
кодируется последовательностью:
Код: Выделить весь код
1110000100101111011011100001001011000011111110
Цитата eg01st:
…а как расшифровывает - пара слов о префиксных кодах, которые я так и не понял.»
Термин «префиксные» обозначает, что никакая кодовая последовательность не является префиксом любой другой кодовой последовательности. Данное свойство позволяет однозначно декодировать любое сообщение. Если Вы посмотрите на полученное нами в примере:
Код: Выделить весь код
1110000100101111011011100001001011000011111110
то убедитесь в этом сами. Выборки одного символа — «1», двух — «11», трёх — «111» входят сразу в несколько кодовых последовательностей, а вот выборка четырёх символов — «1110» — однозначно входит только в одну последовательность, что и позволяет её однозначно идентифицировать с символом исходного сообщения («с» — «1110»).

Данный алгоритм именуется кодом Шеннона — Фано. Как Вы можете увидеть по изложенному выше примеру (и сделанному замечанию), данный алгоритм может давать различные кодовые последовательности, в зависимости от нашего выбора, причём от нашего выбора, сделанного на определённом шаге, будет зависеть разбиение на всех последующих шагах, что, соответственно, не всегда может приводить к наилучшему результату — максимальное сокращение средней длины кодовых последовательностей.

В отличие от вышеизложенного алгоритма Шеннона — Фано, алгоритм Хаффмана, хотя и строится на тех же основных принципах, подразумевает хотя и более сложную реализацию для построения дерева, но приводящую к более лучшему результату. Можно сказать, что, если построить все возможные комбинации кодовых последовательностей по алгоритму Шеннона — Фано (для конкретного сообщения), то среди них будут и все возможные комбинации кодовых последовательностей, построенные по алгоритму Хаффмана.

Впрочем, решив написать данное сообщение, я не ставил задачу обучить Вас тонкостям реализации алгоритма Шеннона — Фано, Хаффмана или Лемпеля — Зива — Велча . Для этих целей хватает и монографий, и пухлых исследований. Я хотел, чтобы Вы примерно поняли сам механизм кодирования с практически нулевой избыточностью (это термин) и саму идею этого алгоритма — максимальное сокращение средней длины кодовых последовательностей. Лучший учитель — практика. Возьмите коллегу. Попросите его закодировать по изложенному выше алгоритму какое-либо сообщение. Пусть он передаст Вам закодированное сообщение и сам словарь. Попробуйте его раскодировать. Тогда Вам станет воочию ясно, что такое префиксные коды и почему «он понимает что нужно преобразовывать символ "а", а не "я"».

Предваряя следующий вопрос, «а что будет, если в переданном сообщении будет искажёны/потеряны какие-либо символы?», скажу, что для этого вводится обратное понятие — избыточность кода, например, широко известные CRC — коды циклического контроля, позволяющие столь же однозначно узнать, было ли сообщение при передаче искажено, и суметь восстановить его. Впрочем, как говорил сказочник, это уже другая история .
Это сообщение посчитали полезным следующие участники:

Отправлено: 05:47, 02-11-2010 | #2



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

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


Новый участник


Сообщения: 3
Благодарности: 0

Профиль | Отправить PM | Цитировать


Большое спасибо за выложенный материал, сейчас пробежал глазами - уже более ясно стало, сегодня вечером буду применять это всё на практике)

Отправлено: 11:23, 02-11-2010 | #3

pva pva вне форума

Аватара для pva

Ветеран


Сообщения: 1180
Благодарности: 279

Профиль | Отправить PM | Цитировать


Iska, если так же понятно расскажешь про арифметическое кодирование, то вообще расцелую

Отправлено: 12:29, 02-11-2010 | #4


Новый участник


Сообщения: 3
Благодарности: 0

Профиль | Отправить PM | Цитировать


Полностью понял и даже проверил. На всякий случай задам вопрос: самые часто встречающиеся 3 символа будут иметь код 00 01 или 10, остальные же, будут иметь код 1110, 11110, 111110, 1111110, 111111110 и дт., а последний, самый редкий символ, будет иметь код 111111111111, то есть, символы с 4-го по n-1 будут заканчиваться на 0, а n - на 1?

Последний раз редактировалось eg01st, 03-11-2010 в 03:13.


Отправлено: 01:09, 03-11-2010 | #5



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » Теория - Алгоритм Хаффмана

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
Разное - Помогите алгоритм составить MaZaFaKa46 Программирование и базы данных 3 28-12-2008 22:00
Алгоритм запуска ПО p13rr0t Хочу все знать 2 11-05-2007 22:00
Алгоритм pauluss Программирование и базы данных 1 06-10-2006 10:53
Подскажите алгоритм wolland Программирование и базы данных 2 27-06-2003 17:56
Алгоритм Чуфа noname00.pas Программирование и базы данных 11 21-09-2002 00:48




 
Переход