UGLYPEAR AI обновил бизнес: высокопроизводительное сжатие документов × RAG-платформа инженерии данныхУзнать о новом направлении →

Принцип кодирования Хаффмана: подробное объяснение основы алгоритмов сжатия

Сразу к выводу: кодирование Хаффмана — оптимальный префиксный код переменной длины. Идея: «частые символы — короткий код, редкие — длинный»; дерево Хаффмана минимизирует общую длину кода. На примере «ABRACADABRA» (11 символов) код фиксированной длины требует 33 бит, Хаффман — всего 23 бит, экономия 30%. Хаффман — ключевой компонент DEFLATE (ZIP/GZIP/PNG) и других форматов сжатия; почти все lossless-алгоритмы включают этот этап. Ниже — от частотного анализа до построения дерева и кодов.

Если вы не знакомы с разницей между сжатием без потерь и с потерями, рекомендуем сначала прочитатьСжатие без потерь vs с потерями: ключевые различия.

1. Зачем нужно кодирование переменной длины

При хранении символов обычно используется кодирование фиксированной длины: ASCII — 8 бит на символ, Unicode — 16-32 бит. Преимущество фиксированной длины — простой произвольный доступ, но при этом огромные потери: в английском тексте буква «e» встречается ~12,7%, «z» — лишь 0,07%, использовать для них одинаковую длину явно нерационально. Кодирование переменной длины назначает разную длину кода в зависимости от частоты: чаще символ — короче код, что уменьшает общий объём.

Метод кодированияПринципдлины кодаНеоднозначность декодированияТипичное применение
Фиксированная длинаN бит на символФиксированаНетASCII, Unicode
Переменная длина (не префиксная)Разная длина по частотеПеременнаВозможнаНепрактично
Префиксный код ХаффманаПо частоте + префиксное ограничениеПеременнаНетDEFLATE, JPEG
Арифметическое кодированиеВсё сообщение в одно числоДробнаяНетZSTD, brotli

Ключевое ограничение кодирования Хаффмана — префиксность: код символа не может быть префиксом кода другого. Например, символ A кодируется как «0», остальные не могут начинаться с «0», только с «1». Декодер читает биты по одному, при обнаружении полного кода сразу декодирует — неоднозначности нет.

2. Подробное описание принципа кодирования Хаффмана

Генерация кода Хаффмана состоит из трёх шагов: частотный анализ, построение дерева Хаффмана и генерация кодовой таблицы. Весь процесс — жадный алгоритм: на каждом шаге выбираются и объединяются два узла с наименьшей частотой, пока не останется один корень — оптимальное бинарное дерево.

1. Частотный анализ

Первый шаг — подсчёт частоты каждого символа. На примере «ABRACADABRA» — сначала подсчитаем, сколько раз встречается каждый символ.

символЧисло вхожденийЧастота (%)Код фиксированной длины (3 бит)
A545.5%000
B218.2%001
R218.2%010
C19.1%011
D19.1%100

5 различных символов требуют ceil(log2(5))=3 бит/символ, всего 11·3=33 бит. Для сравнения, в ASCII требуется 11·8=88 бит — фиксированные 3 бит уже экономят 70%, но Хаффман может сжать ещё сильнее.

2. Построение дерева Хаффмана

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

ШагДействиеДва узла с мин. частотой до объединенияНовый узелОставшиеся узлы
1Объединить C(1) и D(1)C:1, D:1CD:2A:5, B:2, R:2, CD:2
2Объединить B(2) и R(2)B:2, R:2BR:4A:5, CD:2, BR:4
3Объединить CD(2) и BR(4)CD:2, BR:4CDBR:6A:5, CDBR:6
4Объединить A(5) и CDBR(6)A:5, CDBR:6Root:11Готово

После построения из корня идём: левая ветвь — 0, правая — 1, путь до листа — код символа. Самый частый A (5 раз) — на втором уровне, его код всего 1 бит; самые редкие C и D — на нижнем уровне, их код по 3 бита.

3. Генерация кодовой таблицы

Обходим дерево от корня до каждого листа и записываем последовательность 0/1 на пути — это и есть код символа.

символЧастотаКод Хаффманадлины кодаВклад в длину (бит)
A5015×1=5
B210032×3=6
R210132×3=6
C111031×3=3
D111131×3=3

Проверим префиксное свойство: код A «0» не является префиксом никакого другого кода; B «100», R «101», C «110», D «111» — также не префиксы друг друга. При декодировании читаем биты по одному: увидели «0» — это A; увидели «1» — читаем ещё два бита для различения B/R/C/D. Неоднозначности нет.

3. Практический пример: сравнение кодирования «ABRACADABRA»

Закодируем «ABRACADABRA» полученной таблицей и сравним объём при коде фиксированной длины и коде Хаффмана.

Исходный текст: A B R A C A D A B R A (11 символов)

Процесс кодирования:

ПозициясимволКод ХаффманаНакоплено бит
1A01
2B1004
3R1017
4A08
5C11011
6A012
7D11115
8A016
9B10019
10R10122
11A023

Сравнение эффективности:

Метод кодированияБит на символВсего битВсего байтvs ASCIIКоэффициент сжатия
Кодирование ASCII88811— (базовый)
Код фиксированной длины 3 бит333562.5%
Код Хаффмана2,09 (в среднем)23373.9%
Теоретический предел энтропии2.0422.5374.4%

Результат:Кодирование Хаффмана сжало 11 символов с 88 бит ASCII до 23 бит, экономия 73,9%. Даже по сравнению с 3-битным кодом фиксированной длины экономия 30%. Теоретический предел энтропии — 22,5 бит, Хаффман превышает оптимум лишь на 0,5 бит, достигая эффективности 97,8%. Поэтому Хаффман называется оптимальным префиксным кодом.

4. Применение кодирования Хаффмана в основных алгоритмах сжатия

Кодирование Хаффмана редко используется отдельно, обычно это последний этап конвейера сжатия — энтропийное кодирование. Сначала LZ77 и подобные алгоритмы устраняют повторяющиеся шаблоны, затем Хаффман сжимает остаточные данные по частоте. В таблице ниже показано применение Хаффмана в основных форматах.

формат сжатияЭтап словаряэтап энтропийного кодированияВариант ХаффманаТипичное сжатие
DEFLATE (ZIP/GZIP)LZ77HuffmanСтатический + динамический Хаффман50%–70%
PNGLZ77HuffmanВстроенный в DEFLATE Хаффман50%–75%
JPEGDCT-преобразованиеHuffmanРаздельное кодирование DC/AC коэффициентов10:1 (визуально без потерь)
ZSTDВариант LZ77FSE/HuffmanКонечный автомат + Хаффман60%–80%
brotliLZ77 + контекстХаффман + арифметическоеКонтекстный Хаффман65%–85%
BZIP2BWT-преобразованиеHuffmanМноготабличный Хаффман70%–85%

Подробнее о принципе словарного сжатия LZ77 см. вПодробное объяснение алгоритма LZ77: как работает словарное сжатие?. Применение DEFLATE в PNG см. вПодробное объяснение принципа сжатия PNG.

5. Часто задаваемые вопросы (FAQ)

В1: Что такое кодирование Хаффмана?

Кодирование Хаффмана — оптимальный префиксный код переменной длины, предложен Дэвидом Хаффманом в 1952 году. Идея: частые символы получают короткий код, редкие — длинный, общая длина минимизируется. Дерево Хаффмана генерирует таблицу кодов, гарантируя префиксное свойство — ни один код не является префиксом другого, декодирование без неоднозначности.

В2: Почему код Хаффмана — оптимальный префиксный код?

Оптимальность основана на жадной стратегии: на каждом шаге объединяются два узла с наименьшей частотой, редкие символы оказываются в глубине дерева (длинный код), частые — ближе к корню (короткий код). Математически доказано, что для данного распределения частот средняя длина кода Хаффмана не превышает любого другого префиксного кода, достигая теоретического предела энтропийного кодирования (энтропия H). В примере ABRACADABRA код Хаффмана — 23 бит, теоретический предел — 22,5 бит, эффективность 97,8%.

В3: В чём разница между кодом Хаффмана и арифметическим кодированием?

Хаффман кодирует на уровне символов, каждому назначается свой код переменной длины; арифметическое кодирование отображает всё сообщение в одно число из [0,1), гранулярность тоньше. Хаффман проще и быстрее, но ограничен посимвольным кодированием, не достигает предела энтропии. Арифметическое кодирование даёт более высокое сжатие (приближается к энтропии), но вычислительно сложнее. DEFLATE использует Хаффман, современные ZSTD/brotli часто комбинируют оба подхода.

В4: В каких форматах сжатия используется код Хаффмана?

Хаффман — ключевой компонент DEFLATE (ZIP/GZIP/PNG) в связке с LZ77; Zstandard использует FSE (конечный автомат) как альтернативу Хаффману, но принцип схож; brotli и JPEG (DC/AC коэффициенты) также используют Хаффман. Почти все lossless-форматы включают Хаффман или его варианты как этап энтропийного кодирования.

Заключение

Кодирование Хаффмана — основа алгоритмов сжатия, основной принцип: «частые — короткий код, редкие — длинный»; дерево Хаффмана даёт оптимальный префиксный код. На примере «ABRACADABRA» 11 символов сжаты с 88 бит ASCII до 23 бит, эффективность 97,8% от теоретического предела энтропии. Код Хаффмана присутствует почти во всех современных lossless-форматах, в связке с LZ77 он образует классический конвейер сжатия DEFLATE/ZSTD и др.

Ключ к пониманию Хаффмана — три момента:1) частотный анализ определяет длину кодов, 2) жадное построение дерева гарантирует оптимальность, 3) префиксное свойство исключает неоднозначность. Освоив Хаффман, вы получаете ключ к пониманию всех современных алгоритмов сжатия.

Нужно сжать файлы? Попробуйте SmartSlim

Собственный движок сжатия на Rust, поддержка 10+ категорий и более 40 форматов: PDF, изображения, видео, Office, OFD и др. Локальное сжатие — данные не покидают систему.