Алгоритм Хаффмана
Содержание
Определение
Определение: |
Коды или Алгоритм Хаффмана (Huffman codes) — широко распространенный и очень эффективный метод сжатия данных, который, в зависимости от характеристик этих данных, обычно позволяет сэкономить от 20% до 90% объема. |
Рассматриваются данные, представляющие собой последовательность символов. В жадном алгоритме Хаффмана используется таблица, содержащая частоты появления тех или иных символов. С помощью этой таблицы определяется оптимальное представление каждого символа в виде бинарной строки.
Построение кода Хаффмана
В основу алгоритма Хаффмана положена идея: кодировать более коротко те символы, которые встречаются чаще, а те, которые встречаются реже кодировать длиннее. Для построения кода Хаффмана нам необходима таблица частот символов. Рассмотрим пример построения кода на простой строке abacaba
a | b | c | |
---|---|---|---|
4 | 2 | 1 |
Следующим шагом будет построение дерева, где вершины - "символы", а пути до них соответствуют их префиксным кодам. Для этого на каждом шаге будем брать два символа с минимальной частотой вхождения, и объединять их в новые так называемые "символы" с частотой равной сумме частот тех символов, которые мы объединяли. В примере мы объединим символы b и с в символ bc с частотой 3. Файл:Haffman1.jpg
Хаффман изобрел жадный алгоритм, позволяющий составить оптимальный префиксный код, который получил название код Хаффмана. Доказательство корректности этого алгоритма основывается на свойстве жадного выбора и оптимальной подструктуре. Вместо того чтобы демонстрировать, что эти свойства выполняются, а затем разрабатывать псевдокод, сначала мы представим псевдокод. Это поможет прояснить, как алгоритм осуществляет жадный выбор. В приведенном ниже псевдокоде предполагается, что
Huffman( )
for to
- do Выделить память для узла
- left[
] Extract_Min( ) - right[
- Insert(
- left[
return Extract_Min(
Пример работы алгоритма
На каждом этапе показано содержимое очереди, элементы которой рассортированы в порядке возрастания их частот. На каждом шаге работы алгоритма объединяются два объекта (дерева) с самыми низкими частотами. Листья изображены в виде прямоугольников, в каждом из которых указана буква и соответствующая ей частота. Внутренние узлы представлены кругами, содержащими сумму частот дочерних узлов. Ребро, соединяющее внутренний узел с левым дочерним узлом, имеет метку 0, а ребро, соединяющее его с правым дочерним узлом, — метку 1. Слово кода для буквы образуется последовательностью меток на ребрах, соединяющих корень с листом, представляющим эту букву. По скольку данное множество содержит шесть букв, размер исходной очереди равен 6(часть а рисунка), а для построения дерева требуется пять слияний. Промежуточные этапы изображены в частях б-д. Конечное дерево (е) представляет оптимальный префиксный код. Как уже говорилось, слово кода для буквы — это последовательность меток на пути от корня к листу с этой буквой.
В строке 2 инициализируется очередь с приоритетами , состоящая из элементов множества . Цикл for в строках 3-8 поочередно извлекает по два узла, и , которые характеризуются в очереди наименьшими частотами, и заменяет их в очереди новым узлом, представляющим объединение упомянутых выше элементов. Частота появления вычисляется в строке 7 как сумма частот и . Узел является левым дочерним узлом , а — его правым дочерним узлом. (Этот порядок является произвольным; перестановка левого и правого дочерних узлов приводит к созданию другого кода с той же стоимостью.) После объединений в очереди остается один узел — корень дерева кодов, который возвращается в строке 9.
Оценка времени работы
При анализе времени работы алгоритма Хаффмана предполагается, что
реализована как бинарная неубывающая пирамида. Для множества , состоящего из символов, инициализацию очереди в строке 2 можно выполнить за время . Цикл for в строках 3-8 выполняется ровно раз, и поскольку для каждой операции над пирамидой требуется время , вклад цикла во время работы алгоритма равен . Таким образом, полное время работы процедуры Huffman с входным множеством, состоящим из символов, равно .Корректность алгоритма Хаффмана
Чтобы доказать корректность жадного алгоритма Huffman, покажем, что в задаче о построении оптимального префиксного кода проявляются свойства жадного выбора и оптимальной подструктуры. В сформулированной ниже лемме показано соблюдение свойства жадного выбора.
Лемма (1): |
Пусть — алфавит, каждый символ которого встречается с частотой . Пусть и — два символа алфавита с самыми низкими частотами. Тогда для алфавита существует оптимальный префиксный код, кодовые слова символов и в котором имеют одинаковую длину и отличаются лишь последним битом. |
Доказательство: |
Идея доказательства состоит в том, чтобы взять дерево |
Лемма (2): |
Пусть дан алфавит , в котором для каждого символа определены частоты . Пусть и — два символа из алфавита с минимальными частотами. Пусть — алфавит, полученный из алфавита путем удаления символов и и добавления нового символа , так что . По определению частоты в алфавите совпадают с частотами в алфавите , за исключением частоты . Пусть — произвольное дерево, представляющее оптимальный префиксный код для алфавита Тогда дерево , полученное из дерева путем замены листа внутренним узлом с дочерними элементами и , представляет оптимальный префиксный код для алфавита . |
Доказательство: |
Сначала покажем, что стоимость |
Лемма 16.3. Доказательство.
Теорема: |
Процедура Huffman дает оптимальный префиксный код. |
Доказательство: |
Справедливость теоремы непосредственно следует из лемм (1) и (2) |
Литература
- Томас Х. Кормен, Чарльз И. Лейзерсон, Рональд Л. Ривест, Клиффорд Штайн Алгоритмы: построение и анализ — 2-е изд. — М.: «Вильямс», 2007. — С. 1296. — ISBN 5-8489-0857-4