Алгоритм Хаффмана для n ичной системы счисления — различия между версиями
(→Построение кода Хаффмана) |
|||
Строка 67: | Строка 67: | ||
==Построение кода Хаффмана== | ==Построение кода Хаффмана== | ||
− | Приведем жадный алгоритм Хаффмена, строящий оптимальный префиксный код — код Хаффмана. При этом предполагаем, что для любого символа <tex>c \in C</tex> задана его частота f[c]. Также в алгоритме используется очередь с приоритетами Q, которая позволяет найти два объекта с наименьшими частотами для их слияния. | + | Приведем жадный алгоритм Хаффмена, строящий оптимальный префиксный код — код Хаффмана. При этом предполагаем, что для любого символа <tex>c \in C</tex> задана его частота <math>\mathrm{f[c]}</math>. Также в алгоритме используется очередь с приоритетами <math>\mathrm{Q}</math>, которая позволяет найти два объекта с наименьшими частотами для их слияния. |
− | |||
1 n ← |C| | 1 n ← |C| | ||
2 Q ← C | 2 Q ← C |
Версия 14:51, 3 января 2014
Содержание
Алгоритм
Для построения
-ичного кода Хаффмана надо использовать операцию сжатия алфавита, при которой каждый раз сливаются не две, а букв исходного алфавита, имеющих наименьшие вероятности.Сжатие алфавита, при котором букв заменяются на одну, приводит к уменьшению числа букв на ; так как для построения -ичного кода, очевидно, требуется, чтобы последовательность сжатий в конце концов привела нас к алфавиту из букв (сопоставляемых сигналам кода), то необходимо, чтобы число букв первоначального алфавита было представимо в виде , . Этого, однако, всегда можно добиться, добавив, если нужно, к первоначальному алфавиту еще несколько фиктивных букв, вероятности которых считаются равными нулю. После этого построение -ичного кода Хаффмана проводится уже точно так же, как и в случае двоичного кода.Пример
Для примера возьмём слово "кириллица".Возьмем
(троичная система счисления).Алфавит будет к, и, р, л, ц, а , а набор весов . Будем действовать согласно алгоритму выше;у нас число букв первоначального алфавита равно 6.Если подставить значения и в формулу для оптимального кодирования ,то получится что не является целым.Но если увеличить число на 1 (добавлением фиктивной буквы "я" с весом 0) , то можно подобрать целое равное 2. Таким образом можно записать:Узел | к | и | р | л | ц | а | я |
---|---|---|---|---|---|---|---|
Вес | 1 | 3 | 1 | 2 | 1 | 1 | 0 |
По алгоритму возьмем три символа с наименьшей частотой — это я,к,р. Сформируем из них новый узел якр весом 2 и добавим его к списку узлов:
Узел | якр | и | л | ц | а |
---|---|---|---|---|---|
Вес | 2 | 3 | 2 | 1 | 1 |
Затем объединим в один узел узлы л,ц,а:
Узел | якр | и | лца |
---|---|---|---|
Вес | 2 | 3 | 4 |
И, наконец, объединяем три узла якр,и,лца. Итак, мы получили дерево Хаффмана и соответствующую ему таблицу кодов:
Символ | к | и | р | л | ц | а | я |
---|---|---|---|---|---|---|---|
Код | +- | - | +0 | 00 | 0+ | 0- | ++ |
Таким образом, закодированное слово "кириллица" будет выглядеть как "+--+0-0000-0+0-". Длина закодированного слова — 15 бит. Стоит заметить, что если бы мы использовали для кодирования каждого символа из шести по 2 бита, длина закодированного слова составила бы 18 бит.
Корректность алгоритма Хаффмана для -ичной системы счисления
Доказательство аналогично тому,что представлено в теме алгоритм Хаффмана.Только вместо двух символом с минимальными частотами надо брать символов с минимальными частотами (по алгоритму вес символа также может равняться 0).
Задача о подсчете числа бит
Имеются частоты символов,встречающихся в исходном тексте.Необходимо подсчитать суммарное число бит,необходимое для кодирования этого текста.
Возьмем
. На каждом шаге выбираем две наименьшие частоты,объединяем их сумму в одну частоту и добавляем в список вместо двух исходных.Новую частоту прибавляем к с присваиванием.Шаги заканчиваются тогда,когда в списке останется только одна частота.В-итоге,
- число бит необходимое для кодирования этого текстаСложность алгоритма
.Псевдокод алгоритма:
int//исходный массив частот всех n символов,встречающихся в тексте" = 0 do for = 1.. find( , ) //отыскиваем индексы двух минимальных элементов массива swap( [1], [min1]) swap( [2], [min2]) //теперь первые два элемента массива минимальные [2] = [1] + [2] += [2] -- delete( [1]) //убираем из массива ненужный элемент и больше его не рассматриваем while != 1 //пока не останется одна частота в массиве return
Построение кода Хаффмана
Приведем жадный алгоритм Хаффмена, строящий оптимальный префиксный код — код Хаффмана. При этом предполагаем, что для любого символа
задана его частота . Также в алгоритме используется очередь с приоритетами , которая позволяет найти два объекта с наименьшими частотами для их слияния.1 n ← |C| 2 Q ← C 3 for i ← 1 to n - 1 4 do z ← Allocate-Node() 5 x ← left[z] ← Extract-Min(Q) 6 y ← right[z] ← Extract-Min(Q) 7 f[z] ← f[x] + f[y] 8 Insert(Q, z) 9 return Extract-Min(Q) Алгоритм строит оптимальное дерево префиксных кодов. Для этого в цикле выполняется выборка из очереди двух вершин x и y с наменьшими частотами (f[x] и f[y] соответственно), которые заменяются на одну вершину z с частотой f[x] + f[y] и детьми x и y.
Алгоритм работает за O(nlogn) для алфавита из n символов. Считая что, очередь Q реализована в виде двоичной кучи, мы можем выполнить инициализацию Q за O(n), а каждую операцию над кучей за O(logn).