Кодовые деревья
Рассмотрим реализацию алгоритма Хаффмана с использованием кодовых деревьев. Кодовое дерево – это бинарное дерево, у которого:
-
листья помечены символами, для которых разрабатывается кодировка;
-
узлы (в том числе корень) помечены суммой вероятностей появления всех символов, соответствующих листьям поддерева, корнем которого является соответствующий узел.
Существует два подхода к построению кодового дерева: от корня к листьям и от листьев к корню. Рассмотрим первый подход в виде процедуры Паскаля. Входными параметрами этой процедуры являются массив используемых символов, отсортированный в порядке убывания вероятности появления символов (в начале идут символы с максимальными вероятностями, а в конце – с минимальными), а также указатель на создаваемое кодовое дерево, описание которого идентично описанию бинарного дерева в виде списков (см. п. 2.3.4.4), за исключением того, что поле Data здесь принимает символьный тип.
procedure CreateCodeTable(UseSimbol: TUseSimbol;
var CodeTree: PTree);
{Процедура создания кодового дерева по методу Хаффмана}
var
Current: PTree;
SimbolCount: integer;
begin
{Создаем корень кодового дерева}
new(CodeTree);
Current := CodeTree;
Current^.Left := nil; Current^.Right := nil;
SimbolCount := 1;
{Создаем остальные вершины}
while SimbolCount <= n-1 do begin
{Создаем лист с символом в виде левого потомка}
new(Current^.Left);
Current^.Left^.Data := UseSimbol[SimbolCount];
Current^.Left^.Left := nil; Current^.Left^.Right := nil;
{Создаем следующий узел в виде правого потомка}
new(Current^.Right);
Current := Current^.Right;
Current^.Left := nil; Current^.Right := nil;
SimbolCount := SimbolCount + 1;
end;
{Последний узел превращаем в лист с символом}
Current^.Data := UseSimbol[SimbolCount];
end;
Рисунок 39. Создание оптимальных префиксных кодов
Созданное кодовое дерево может быть использовано для кодирования и декодирования текста. Как осуществляется кодирование уже говорилось выше. Теперь рассмотрим процесс декодирования. Алгоритм распаковки кода можно сформулировать следующим образом.
procedure DecodeHuffman(CodeTree: PTree; var ResultStr: string);
{Процедура декодирования по методу Хаффмана из некоторой битовой}
{последовательности в результирующую строку ResultStr}
var
Current: PTree; {Указатель в дереве}
CurrentBit, {Значение текущего бита кода}
CurrentSimbol: integer; {Индекс распаковываемого символа}
FlagOfEnd: boolean; {Флаг конца битовой послед-ти}
begin
{Начальная инициализация}
FlagOfEnd := false; CurrentSimbol := 1; Current := CodeTree;
{Пока не закончилась битовая последовательность}
while not FlagOfEnd do begin
{Пока не пришли в лист дерева}
while (Current^.Left <> nil) and
(Current^.Right <> nil) and
not FlagOfEnd do begin
{Читаем значение очередного бита}
CurrentBit := ReadBynary(FlagOfEnd);
{Бит – 0, то идем налево, бит – 1, то направо}
if CurrentBit = 0 then Current := Current^.Left
else Current := Current^.Right;
end;
{Пришли в лист и формируем очередной символ}
ResultStr[CurrentSimbol] := Current^.Data;
CurrentSimbol := CurrentSimbol + 1;
Current := CodeTree;
end;
end;
В приведенном алгоритме используется функция ReadBinary, которая читает битовую последовательность и возвращает целое значение 0, если текущий бит равен 0 и возвращает 1, если бит равен 1. Кроме того, она формирует флаг конца битовой последовательности: он принимает значение true, если последовательность исчерпана.
Для осуществления распаковки необходимо иметь кодовое дерево, которое приходится хранить вместе со сжатыми данными. Это приводит к некоторому незначительному увеличению объема сжатых данных. Используются самые различные форматы, в которых хранят это дерево. Здесь следует отметить, что узлы кодового дерева являются пустыми. Иногда хранят не само дерево, а исходные данные для его формирования, то есть сведения о вероятностях появления символов (или их количествах). При этом процесс декодирования предваряется построением нового кодового дерева, которое будет таким же, как и при кодировании.
- Содержание
- Основные сведения
- Понятия алгоритма и структуры данных
- Анализ сложности и эффективности алгоритмов и структур данных
- Структуры данных
- Элементарные данные
- Данные числовых типов
- Данные целочисленного типа
- Данные вещественного типа
- Операции над данными числовых типов
- Данные символьного типа
- Данные логического типа
- Данные типа указатель
- Линейные структуры данных
- Множество
- Линейные списки
- Линейный однонаправленный список
- Линейный двунаправленный список
- Циклические списки
- Циклический однонаправленный список
- Циклический двунаправленный список
- Разреженные матрицы
- Матрицы с математическим описанием местоположения элементов
- Матрицы со случайным расположением элементов
- Очередь
- Нелинейные структуры данных
- Мультисписки
- Слоеные списки
- Спецификация
- Реализация
- Деревья
- Общие сведения
- Обходы деревьев
- Спецификация двоичных деревьев
- Реализация
- Основные операции
- Организация
- Представление файлов b-деревьями
- Основные операции
- Общая оценка b-деревьев
- Алгоритмы обработки данных
- Методы разработки алгоритмов
- Метод декомпозиции
- Динамическое программирование
- Поиск с возвратом
- Метод ветвей и границ
- Метод альфа-бета отсечения
- Локальные и глобальные оптимальные решения
- Алгоритмы поиска
- Поиск в линейных структурах
- Последовательный (линейный) поиск
- Бинарный поиск
- Хеширование данных
- Функция хеширования
- Открытое хеширование
- Закрытое хеширование
- Реструктуризация хеш-таблиц
- Поиск по вторичным ключам
- Инвертированные индексы
- Битовые карты
- Использование деревьев в задачах поиска
- Упорядоченные деревья поиска
- Случайные деревья поиска
- Оптимальные деревья поиска
- Сбалансированные по высоте деревья поиска
- Поиск в тексте
- Прямой поиск
- Алгоритм Кнута, Мориса и Пратта
- Алгоритм Боуера и Мура
- Алгоритмы кодирования (сжатия) данных
- Общие сведения
- Метод Хаффмана. Оптимальные префиксные коды
- Кодовые деревья
- Алгоритмы сортировки
- Основные сведения. Внутренняя и внешняя сортировка
- Алгоритмы внутренней сортировки
- Сортировка подсчетом
- Сортировка простым включением
- Сортировка методом Шелла
- Сортировка простым извлечением.
- Древесная сортировка
- Сортировка методом пузырька
- Быстрая сортировка (Хоара)
- Сортировка слиянием
- Сортировка распределением
- Сравнение алгоритмов внутренней сортировки
- Алгоритмы внешней сортировки
- Алгоритмы на графах
- Алгоритм определения циклов
- Алгоритмы обхода графа
- Поиск в глубину
- Поиск в ширину (Волновой алгоритм)
- Нахождение кратчайшего пути
- Алгоритм Дейкстры
- Алгоритм Флойда
- Переборные алгоритмы
- Нахождение минимального остовного дерева
- Алгоритм Прима
- Алгоритм Крускала
- 190000, Санкт-Петербург, ул. Б. Морская, 67