Алгоритм Хаффмана — различия между версиями
System29a (обсуждение | вклад) |
(→Корректность алгоритма Хаффмана) |
||
Строка 28: | Строка 28: | ||
== Корректность алгоритма Хаффмана == | == Корректность алгоритма Хаффмана == | ||
− | Чтобы доказать корректность жадного алгоритма Huffman, покажем, что в | + | Чтобы доказать корректность жадного алгоритма Huffman, покажем, что в задаче о построении оптимального префиксного кода проявляются свойства жадного выбора и оптимальной подструктуры. В сформулированной ниже лемме показано соблюдение свойства жадного выбора. |
− | + | ||
− | выбора и оптимальной подструктуры. В сформулированной ниже лемме показано | + | {{Лемма |
− | соблюдение свойства жадного выбора. | + | |id=lemma1 |
− | Лемма | + | |about=1 |
− | + | |statement=Пусть <tex>C</tex> — алфавит, каждый символ <tex>c \in C</tex> которого встречается с частотой <tex>f[c]</tex>. Пусть <tex>x</tex> и <tex>y</tex> — два символа алфавита <tex>C</tex> с самыми низкими частотами. Тогда для алфавита <tex>C</tex> существует оптимальный префиксный код, кодовые слова символов <tex>x</tex> и <tex>y</tex> в котором имеют одинаковую длину и отличаются лишь последним битом. | |
− | Тогда для алфавита | + | |proof=Идея доказательства состоит в том, чтобы взять дерево <tex>T</tex>, представляющее произвольный оптимальный префиксный код, и преобразовать его в дерево, представляющее другой оптимальный префиксный код, в котором символы <tex>x</tex> и <tex>y</tex> являются листьями с общим родительским узлом, причем в новом дереве эти листья находятся на максимальной глубине. Пусть <tex>a</tex> и <tex>b</tex> — два символа, представленные листьями с общим родительским узлом, которые находятся на максимальной глубине дерева <tex>T</tex>. Предположим без потери общности, что <tex>f[a] \le f[b]</tex> и <tex>f[x] \le f[y]</tex>. Поскольку <tex>f[x]</tex> и <tex>f[y]</tex> — две самые маленькие частоты (в указанном порядке), <tex>f[a]</tex> и <tex>f[b]</tex> — две произвольные частоты, то выполняются соотношения <tex>f[x] \le f[a]</tex> и <tex>f[y] \le f[b]</tex>. В результате перестановки в дереве <tex>T</tex> листьев <tex>a</tex> и <tex>x</tex> получается дерево <tex>T'</tex>, а при последующей перестановке в дереве V листьев <tex>b</tex> и <tex>y</tex> получается дерево <tex>T''</tex>. Разность стоимостей деревьев Т и Т" равна <br> |
− | символов | + | <tex>B(T) - B(T') = \sum_{c \in C} f(c)d_T(C) - \sum_{c \in C} f(c)d_{T'}(C) =</tex><br><tex> = (f[a] - f[x])(d_T(a) - d_T(x)) \ge 0</tex>,<br> |
− | битом. | + | поскольку величины <tex>f[a] - f[x]</tex> и <tex>d_T(a) - d_T(x)</tex> неотрицательны. Величина <tex>f[a] - f[x]</tex> неотрицательна, потому что х — лист с минимальной частотой, величина <tex>d_T(a) - d_T(x)</tex> неотрицательна, потому что <tex>a</tex> — лист на максимальной глубине в дереве <tex>T</tex>. Аналогично, перестановка листьев <tex>y</tex> и <tex>b</tex> не приведет к увеличению стоимости, поэтому величина <tex>B(T') - B(T'')</tex> неотрицательна. Таким образом, выполняется неравенство <tex>B(T') \le B(T'')</tex>, и поскольку <tex>T</tex> — оптимальное дерево, то должно также выполняться неравенство <tex>B(T'') \le B(T')</tex>, откуда следует, что <tex>B(T') = B(T'')</tex>. Таким образом, <tex>T''</tex> — оптимальное дерево, в котором <tex>x</tex> и <tex>y</tex> — находящиеся на максимальной глубине дочерние листья одного и того же узла, что и доказывает лемму. |
− | + | }} | |
− | + | ||
− | в дерево, представляющее другой оптимальный префиксный код, в котором | + | {{Лемма |
− | + | |id=lemma2. | |
− | дереве эти листья находятся на максимальной глубине. | + | |about=2 |
− | Пусть | + | |statement=Пусть дан алфавит <tex>C</tex>, в котором для каждого символа <tex>c \in C</tex> определены частоты <tex>f[c]</tex>. Пусть <tex>x</tex> и <tex>y</tex> — два символа из алфавита <tex>C</tex> с минимальными частотами. Пусть <tex>C'</tex> — алфавит, полученный из алфавита <tex>C</tex> путем удаления символов <tex>x</tex> и <tex>y</tex> и добавления нового символа <tex>z</tex>, так что <tex>C = C — {х,у} \cup {z}</tex>. По определению частоты <tex>f</tex> в алфавите <tex>C'</tex> совпадают с частотами в алфавите <tex>C</tex>, за исключением частоты <tex>f[z] = f[x] + f[y]</tex>. Пусть <tex>T'</tex> — произвольное дерево, представляющее оптимальный префиксный код для алфавита <tex>C'</tex> Тогда дерево <tex>T</tex>, полученное из дерева <tex>T'</tex> путем замены листа <tex>z</tex> внутренним узлом с дочерними элементами <tex>x</tex> и <tex>y</tex>, представляет оптимальный префиксный код для алфавита <tex>C</tex>. |
− | узлом, которые находятся на максимальной глубине дерева | + | |proof=Сначала покажем, что стоимость <tex>B(T)</tex> дерева <tex>T</tex> можно выразить через стоимость <tex>B(T')</tex> дерева <tex>T'</tex>. Для каждого символа <tex>c \le C - {x,y}</tex> выполняется соотношение <tex>d_T(C) = d_{T'}(c)</tex>, следовательно, <tex>f[c]d_T(C) = f[c]d_{T'}(c)</tex>. Поскольку <tex>d_T(x) = d_{T}(y) = d_{t'}(z) + 1</tex>, получаем соотношение<br> |
− | потери общности, что | + | <tex>f[x]d_T(x) + f[y]d_{T}(y) = (f[x] + f[y])(d_{T'}(z) + 1) = f[z]d_{T'}(z) + (f[x] + f[y])</tex> |
− | самые маленькие частоты (в указанном порядке), | + | <br> |
− | частоты, то выполняются соотношения f[x] | + | из которого следует равенство <br> |
− | + | <tex> B(T) = B(T') + f[x] + f[y] </tex> <br> | |
− | + | ИЛИ <br> | |
− | + | <tex> B(T') = B(T) - f[x] - f[y] </tex>. <br> | |
− | + | Докажем лемму методом от противного. Предположим, дерево <tex> T </tex> не представляет оптимальный префиксный код для алфавита <tex> C </tex>. Тогда существует дерево <tex> T'' </tex>, для которого справедливо неравенство <tex> B(T'') < B(T) </tex>. Согласно лемме (1), <tex>x</tex> и <tex>y</tex> без потери общности можно считать дочерними элементами одного и того же узла. Пусть дерево <tex>T'''</tex> получено из дерева <tex>T''</tex> путем замены элементов <tex>x</tex> и <tex>y</tex> листом <tex>z</tex> с частотой <tex>f[z] = f[x] + f[y] </tex>. Тогда можно записать:<br> | |
− | + | <tex>B(T''') = B(T'') - f[x] - f[y] < B(T) - f[x] -f[y] = B(T')</tex>,<br> | |
− | поскольку величины | + | что противоречит предположению о том, что дерево <tex>T'</tex> представляет оптимальный префиксный код для алфавита <tex>C'</tex>. Таким образом, дерево <tex>T</tex> должно представлять оптимальный префиксный код для алфавита <tex>C</tex>. |
− | - f [ | + | }} |
− | ( | + | |
− | + | Лемма 16.3. | |
− | + | Доказательство. | |
− | в дереве | ||
− | стоимости, поэтому величина | ||
− | выполняется неравенство | ||
− | то должно также выполняться неравенство | ||
− | |||
− | находящиеся на максимальной глубине дочерние листья одного и того же узла, | ||
− | что и доказывает лемму. | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | частотами. Пусть | ||
− | |||
− | По определению частоты / в алфавите | ||
− | за исключением частоты | ||
− | представляющее оптимальный префиксный код для алфавита | ||
− | полученное из дерева | ||
− | элементами | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | из которого следует равенство | ||
− | B(T) = B(T')+f[x | ||
− | ИЛИ | ||
− | B | ||
− | Докажем лемму методом от противного. Предположим, дерево | ||
− | |||
− | для которого справедливо неравенство | ||
− | и | ||
− | же узла. Пусть дерево | ||
− | листом z с частотой | ||
− | B(T | ||
− | что противоречит предположению о том, что дерево | ||
− | префиксный код для алфавита | ||
− | оптимальный префиксный код для алфавита | ||
{{Теорема | {{Теорема | ||
|id=th1 | |id=th1 | ||
Строка 110: | Строка 62: | ||
Процедура Huffman дает оптимальный префиксный код. | Процедура Huffman дает оптимальный префиксный код. | ||
|proof= | |proof= | ||
− | Справедливость теоремы непосредственно следует из лемм 1 и 2 | + | Справедливость теоремы непосредственно следует из лемм (1) и (2) |
}} | }} |
Версия 09:41, 29 октября 2010
Содержание
Определение
Определение: |
Коды или Алгоритм Хаффмана (Huffman codes) — широко распространенный и очень эффективный метод сжатия данных, который, в зависимости от характеристик этих данных, обычно позволяет сэкономить от 20% до 90% объема. |
Рассматриваются данные, представляющие собой последовательность символов. В жадном алгоритме Хаффмана используется таблица, содержащая частоты появления тех или иных символов. С помощью этой таблицы определяется оптимальное представление каждого символа в виде бинарной строки.
Построение кода Хаффмана
Хаффман изобрел жадный алгоритм, позволяющий составить оптимальный префиксный код, который получил название код Хаффмана. Доказательство корректности этого алгоритма основывается на свойстве жадного выбора и оптимальной подструктуре. Вместо того чтобы демонстрировать, что эти свойства выполняются, а затем разрабатывать псевдокод, сначала мы представим псевдокод. Это поможет прояснить, как алгоритм осуществляет жадный выбор. В приведенном ниже псевдокоде предполагается, что
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) |