Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Kodirovanie_dlya_Filiala_v_g_Izhevske.doc
Скачиваний:
0
Добавлен:
27.12.2019
Размер:
390.14 Кб
Скачать

1.4.2. Кодирование по Хаффмену. Дерево Хаффмена.

В конце сороковых годов, на заре развития теории информации, идеи разработки новых эффективных способов кодирования информации носились в возду­хе. Исследователи занимались вопросами энтропии, содержимого информации и избыточности. Интерес­но, что эти первоначальные работы в области сжатия информации велись до появления современного циф­рового компьютера. Сегодня теория информации раз­вивается параллельно с программированием, но в то время идея разработки алгоритмов, использующих двоичную арифметику для кодирования символов, была значительным шагом вперед.

Один из первых алгоритмов эффективного кодиро­вания информации был предложен Д. А.Хаффменом в 1952 году. Идея алгоритма состоит в следующем: зная вероятности вхождения символов в сообщение, мож­но описать процедуру построения кодов переменной длины, состоящих из целого количества битов. Сим­волам с большей вероятностью присваиваются более короткие коды. Коды Хаффмена имеют уникальный префикс, что и позволяет однозначно их декодиро­вать, несмотря на их переменную длину.

Классический алгоритм Хаффмена на входе полу­чает таблицу частот встречаемости символов в сооб­щении. Далее на основании этой таблицы строится дерево кодирования Хаффмена (Н-дерево). Алгоритм построения Н-дерева прост и элегантен.

1. Символы входного алфавита образуют список свободных узлов. Каждый лист имеет вес, который может быть равен либо вероятности, либо количест­ву вхождений символа в сжимаемое сообщение.

2. Выбираются два свободных узла дерева с наи­меньшими весами.

3. Создается их родитель с весом, равным их сум­марному весу.

4. Родитель добавляется в список свободных узлов, а двое его детей удаляются из этого списка.

5. Одной дуге, выходящей из родителя, ставится в соответствие бит 1, другой — бит 0.

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

Допустим, у нас есть следующая таблица частот:

А

Б

В

Г

Д

15

7

6

6

5


На первом шаге из листьев дерева выбираются два с наименьшими весами — Г и Д. Они присоединяются к новому узлу-родителю, вес которого устанавлива­ется в 5+6 = 11. Затем узлы Г и Д удаляются из списка свободных. Узел Г соответствует ветви 0 родителя, узел Д — ветви I.

На следующем шаге то же происходит с узлами Б и В, так как теперь эта пара имеет самый меньший вес в дереве. Создается новый узел с весом 13, а узлы Б и В удаляются из списка свободных. После всего этого дере­во кодирования выглядит так, как показано на рис. 1,

13

11

0 1 0 1

15

7

6

6

5

А

Б

В

Г

Д

Рис. Дерево кодирования Хаффмена после второго шага

На следующем шаге «наилегчайшей» парой оказы­ваются узлы Б/В и Г/Д. Для них еще раз создается родитель, теперь уже с весом 24. Узел Б/В соответст­вует ветви 0 родителя, Г/Д — ветви 1.

На последнем шаге в списке свободных осталось толь­ко два узла — это А и узел (Б/В)/(Г/Д). В очередной раз создается родитель с весом 39 и бывшие свободными узлы присоединяются к разным его ветвям.

Поскольку свободным остался только один узел, то алгоритм построения дерева кодирования Хаффмена завершается. Н-дерево представлено на следующем рисунке

  1. 1

    39

24

0 1

13

11

0 1 0 1

15

7

6

6

5

А

Б

В

Г

Д

Рис. Окончательное дерево кодирования Хаффмена

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

Для данной таблицы символов коды Хаффмена бу­дут выглядеть следующим образом.

А

Б

В

Г

Д

0

100

101

110

111


Поскольку ни один из полученных кодов не являет­ся префиксом другого, они могут быть однозначно декодированы при чтении их из потока. Кроме того, наиболее частый символ сообщения А закодирован наименьшим количеством битов, а наиболее редкий символ Д — наибольшим.

Классический алгоритм Хаффмена имеет один су­щественный недостаток. Для восстановления содер­жимого сжатого сообщения декодер должен знать таб­лицу частот, которой пользовался кодер. Следова­тельно, длина сжатого сообщения увеличивается на длину таблицы частот, которая должна посылаться впереди данных, что может свести на нет все усилия по сжатию сообщения. Кроме того, необходимость на­личия полной частотной статистики перед началом собственно кодирования требует двух проходов по со­общению: одного для построения модели сообщения (таблицы частот и Н-дерева), другого для собственно кодирования.

$ 1.5. Арифметическое кодирование.

Кодирование Хаффмена при сжатии информации коди­рует каждый символ сжимаемого сообщения це­лым количеством битов. Если частота встречае­мости некоторого символа в сообщении очень ве­лика, например 90 из 100, то было бы в принципе возможно поставить в соответствие этому симво­лу код длиной 0,15 бита. Однако схема кодирова­ния Хаффмена может в лучшем случае закоди­ровать такой символ в 1 бит, что в 6 раз менее эффективно.

В 70-е годы у алгоритма Хаффмена появился достойный конкурент — арифметическое кодиро­вание. Этот метод основан на идее преобразования входного потока в одно число с плавающей запя­той. Естественно, что чем длиннее сообщение, тем длиннее получающееся в результате кодирования число. Итак, на выходе арифметического компрес­сора получается число, меньшее 1 и большее либо равное 0. Из этого числа можно однозначно восста­новить последовательность символов, из которых

оно было построено.

Рассмотрим работу арифметического компрессора на при­мере сообщения «BILL GATES».

Поставим в соответ­ствие каждому симво­лу сообщения вероят­ность его появления в сообщении. Затем присвоим каждому символу ин­тервал вероятности в промежутке от 0 до 1. Длина интервала для сим­вола равна вероятности его появления в сообще­нии. Положение интервала вероятности каждого символа не имеет значения. Важно только то, чтобы и кодер, и декодер располагали символы по одинаковым правилам. Интервалы вероятности для символов нашего сообщения приведены в следующей таблице.

Символ

Вероятность

Интервал

(нижняя и верхняя границы)

Пробел

1/10

[0.00,0.10]

A

1/10

[0.10,0.20]

B

1/10

[0.20,0.30]

E

1/10

[0.30,0.40]

G

1/10

[0.40,0.50]

I

1/10

[0.50,0.60]

L

2/10

[0.60,0.80]

S

1/10

[0.80,0.90]

T

1/10

[0.90,1.00]

В общем виде алгоритм арифметического коди­рования может быть описан следующим образом:

Нижняя граница=0.0;

Верхняя граница=1.0;

Пока ( Очередной символ = Дай Очередной символ ( ))

Интервал =ВерхняяГраница – НижняяГраница ;

ВерхняяГраница = НижняяГраница + Интервал * ВерхняяГраницаИнтервалаДля ( ОчереднойСимвол );

НижняяГраница = НижняяГраница + Интервал * НижняяГраницаИнтервалаДля( ОчереднойСимвол);

Конец Пока

Выдать (Нижняя граница )

Для нашего случая алгоритм кодирования будет работать следующим образом:

Протокол кодирования:

Очередной

символ

Нижняя

Граница

Верхняя

Граница

Начало:

0.0

1.0

B

0.2

0.3

I

0.25

0.26

L

0.256

0.258

L

0.2572

0.2576

Пробел

0.25720

0.25724

G

0.257216

0.257220

A

0.2572164

0.2572168

T

0.25721676

0.2572169

E

0.257216772

0.257216776

S

0.2572167752

0.2572167756


Алгоритм арифметического декодирования может быть описан следующим образом:

Число = ПрочитатьЧисло ();

Всегда

Символ = НайтиСимволВинтервалКоторогоПопадаетЧисло (Число)

Выдать (Символ)

Интервал = ВерхняяГраницаИнтервалаДля( символ ) - НижняяГраницаИнтервалаДля( Символ);

Число = Число – НижняяГраницаИнтервалаДля(Символ );

Число= Число / Интервал;

КонецВсегда

Для нашего примера декодер будет работать следу­ющим образом:

Протокол декодирования

Число

Символ

НижняяГраница

ВерхняяГраница

Интервал

0.2572167752

В

0.2

0.3

0.1

0.572167752

I

0.5

0.6

0.1

0.72167752

L

0.6

0.8

0.2

0.6083876

L

а 6

0.8

0.2

0.041938

Пробел

0.0

0.1

0.1

0.41938

G

0.4

0.5

0.1

0.1938

А

0.2

0.3

0.1

0.938

Т

0.9

1.0

0.1

0.38

Е

0.3

0.4

0.1

0.8

S

0.8

0.9

0.1

0.0

Таким образом, при обработке числа после опреде­ления символа, в интервал которого оно попадает, этот символ выдается как раскодированный, а его влияние на число устраняется действиями, обратны­ми действиям при кодировании.

Замечание.

Из всего сказанного не видно, в чем преимущество арифметического кодирования перёд кодированием Хаффмена. Разница становится заметна тогда, когда частота встречаемости символов во входном сообще­нии сильно отличается друг от друга.

Пусть заранее известна вероятность появления символа 'Ш' в некотором сообщении, и она равна 0.9.

В следующей таблице показано то, как алгоритм арифметиче­ского кодирования обработает сообщение «ШШШШШШШ!».

Арифметическое кодирование сообщения «ШШШШШШШ!»

ОчереднойСимвол

НижняяГраница

ВерхняяГраннца

0.0

1.0

Ш

0.0

0.9

Ш

0.0

0.81

Ш

0.0

0.729

Ш

0.0

0.6561

Ш

0.0

0.59049

Ш

0.0

0.531441

Ш

0.0

0.4782969

!

0.43046721

0.4782969

Очевидно, что число 0.4375 (в двоичном виде 0.0111) может однозначно закодировать это сообще­ние. Это значит, что мы закодировали сообщение дли­ной 8 символов в 4 бита. Оптимальное кодирование Хаффмена могло бы дать минимум 8 битов.

Эксперименты на различных типах данных пока­зывают, что арифметическое кодирование всегда дает результаты не хуже, чем кодирование Хаффмена. В некоторых случаях выигрыш может быть очень суще­ственным. Однако в силу того, что объем вычислений, необходимых при работе алгоритма арифметического кодирования, значительно выше, чем при кодировании по методу Хаффмена, он работает медленнее. Арифметическое кодирование может быть использовано в тех случаях, когда степень сжатия важнее, чем временные затраты на сжатие информации.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]