Код Хаффмана

Под кодированием символов из некоторого множества будем понимать установление соответствия каждому из них некоторой битовой последовательности. Мы уже давно знакомы с некоторыми кодировки. Например с 7-битной ASCII кодировкой или 8-битной Windows-1251. Это так намазываемые равномерные кодировки. Это означает, что длина кодирующей последовательности одинакова для всех символов.
Идея кодирования Хаффмана состоит в отказе от равномерности кода — символы, которые встречаются в кодируемом тексте чаще предполагается кодировать более короткими битовыми последовательностями. Такие коды в которых длина кодов различных символов отличается, называют неравномерными.
Алгоритм Хафмана, является примером жадного алгоритма в котором строится бинарное дерево листьями которого являются символы текста. Глубина листа (расстояние до корня) тем меньше, чем выше встречаемость символа в тексте. Бинарное дерево кода строится путем последовательного объединения наиболее редких символов. При этом образуется новая вершина, соответствующая множеству объединяемых символов. Новой вершине приписывается частота равная сумме частот объединяемых вершин.
Процесс объединения продолжается до получения дерева. Т.е. в списке множеств символов останется только один элемент — объединение всех символов текста. Частота этого последнего узла равна количеству символов в тексте.
Например, возьмем английскую поговорку «so many men, so many minds». Сосчитаем сколько раз встретилась каждая буква и построим дерево префиксного кодирования по алгоритму Хаффмана. Получится что-то вроде такого:

so many men, so many minds

so many men, so many minds

Если одно из детей вершины обозначить через 0, а другого — 1, то путь от корня к листику можно задать последовательностью нулей и единиц. Чем дальше от корня будет расположен лист, тем длиннее будет код. Поскольку мы каждый раз объединяли вершины с наименьшей частотой, у «редких» вершин будет длинный код, а у частых — короткий.

Для написания программы решения задачи я использовал очередь с приоритетами. Программа генерирует код и печатает текст, запроса к сервису Google, который рисует соответствующее дерево.
Сам код приведен ниже.

Конечно, код нуждается в подробных пояснениях и значительном улучшении. Но я сознательно этого не делаю. Пусть это будет упражнением для студентов.

Задание 1

    Постройте код Хафмана для своей фамилии, имени и отчества. Для этого решите следующие задачи:

  1. Вычислите частоту встречаемости букв.
  2. Постройте граф Хафмана обозначив 0 и 1-ребра.
  3. Закодируйте этот граф на языке DOT и постройте изображение в любом онлайн визуализаторе.
  4. Сделайте таблицу с кодами Хафмана для этих букв.
  5. Запишите двоичный код исходного текста.
  6. Сравните длину равномерного и Хафмановского кодирования для этого числа букв и этого конкретного текста. Объясните результат. Что может на него повлиять?
  7. Опишите результаты работы в виде странички на replit.com с использованием HTML и CSS. Не забудьте сделать правильную разметку с использованием заголовков. Рисунок вставьте в формате SVG. Если дополнительная оценка по курсу «Основы Интернет технологий» вам не нужна, то можно использовать документы Google. В любом случае, пришлите для проверки ссылку на работу Вашему преподавателю.

Задание 2

    Написать программу декодирования любоq 01-последовательности на основании некоторого кода Хафмана (с порождением исключительной ситуации если символ не был распознан). Для этого:

  1. Разрабатываем класс BinarySequention для хранения битовой последовательности произвольной длины.
  2. Разрабатываем класс HuffmanCode для хранения кода Хафмана в котором для некоторых символов char задается их 01-код в виде BinarySequention.
  3. Разрабатываем функцию string decode (HuffmanCode h, BinarySequention t), которая декодирует (если возможно) битовую последовательность и возвращает строку текста
  4. Пришлите ссылку преподавателю для проверки.

Related Images: