Изменения

Перейти к: навигация, поиск

Оптимальное хранение словаря в алгоритме Хаффмана

1393 байта добавлено, 16:25, 15 января 2015
Используемая память
=== Передача информации для восстановления листьев ===
Алфавит нам будет дан изначально, не будет лишь кодов каждого символа, следовательно нам нужно просто указать, какой лист в дереве соответствует каждому символу. Занумеруем подряд все символы алфавита. Сопоставим каждому символу алфавита код фиксированной <tex>c'</tex> длины <tex> \lceil \log _2 \rceil n</tex> — его порядковый номер в алфавите, записанный в двоичной системе счисления. Все коды имеют фиксированную длину, а значит легко понять где заканчивается один, и начинается другой код. Тогда, если выписать подряд коды <tex>c'</tex> для всех символов в том порядке, в котором обход в глубину посещает соответствующие им листы, несложно восстановить, какому символу какой код <tex>c</tex> соответствует. Когда мы, в результате обхода в глубину, пришли в вершину, у которой нет детей, мы возьмем следующий переданный нам номер, посмотрим в нашем алфавите что это за символ, и присвоим текущей вершине этот символ.
Алфавит у нас будет изначально=== Отсутствие некоторых символов в тексте ===Предположим теперь, что не будет лишь кодов каждого символа, следовательно нам нужно просто указать, какой лист в дереве соответствует каждому символу. Занумеруем подряд все символы из алфавита. Сопоставим каждому символу алфавита код фиксированной <tex>c'</tex> длины <tex> \lceil \log _2 \rceil n</tex> — его порядковый номер были использованы в алфавитетексте, записанный в двоичной системе счисления. Все коды имеют фиксированную длину, а значит легко понять где заканчивается один, и начинается другой тогда возникает вопрос: получив очередной код. Тогда, если выписать как узнать какому символу он принадлежит? Для решения этой проблемы поступим следующим образом: выпишем подряд коды <tex>c'</tex> для всех символов в том порядке, в котором обход в глубину посещает соответствующие им листы, несложно восстановитьлишь для тех символов, какому символу какой код <tex>c</tex> соответствуетчто были использованы в нашем сообщении. Когда мы, в результате обхода в глубину, пришли в вершину, у которой нет детейТогда встретив очередной символ, мы возьмем следующий переданный нам номергарантированно будем знать, посмотрим что он встречался в нашем алфавите что это за символ, и присвоим текущей вершине этот символсообщении.
=== Используемая память ===
Итого, задача решена с использованием <tex>n \lceil \log_2 \rceil n + 2n - 1 + 32 = n \lceil \log_2 \rceil n + 2n + 31 </tex> бит.
 
Если же были использованы не все символы, то будет использовано <tex>k \lceil \log_2 \rceil n + 2k - 1 + 32 = k \lceil \log_2 \rceil n + 2k + 31 </tex> бит, где <tex>k</tex> — количество использованных символов.
=== Реализация ===
<span style="color:Green">// s — наша строка обхода, tree[] — дерево вершин, code — текущий код, alphabet[] — массив кодов символов, </span> <span style="color:Green">// c'[] — номера символов в порядке обхода</span> '''function''' huffman(): <span style="color:Green">//текущая вершина - корень дерева</span> curV = root '''for''' i = 0..n - 2 '''if''' s[i] == 'D' curV = tree[curV].leftChild code += '0' '''if''' curV не имеет детей alphabet[следующий номер c'].push(code) '''else''' '''while''' curV является правым ребенком и curV не корень curV = tree[curV].parent удалить из code последний символ curV = tree[curV].rightChild code += '1' '''if''' curV не имеет детей alphabet[следующий номер c'].push(code) === Смотрите также ===
== См. также ==
*[[Алгоритм_Хаффмана_за_O(n) | Алгоритм Хаффмана за O(n)]]
32
правки

Навигация