Основы кодирования: префиксные коды и неравенство Крафта
Почему ни одно кодовое слово не должно быть началом другого: дерево кода, неравенство Крафта, код Хаффмана по шагам и нижняя граница через энтропию.
Архиватор сжал документ с трёх мегабайт до полутора — без потерь: после распаковки совпал каждый байт. Откуда берётся такая щедрость? Из неравномерного кода: частые символы получают короткие цепочки бит, редкие — длинные. Схема работает, пока не возникает вопрос, который легко задать и трудно пережить: раз слова разной длины, где кончается одно слово и начинается следующее? Теория кодирования отвечает на него строго — через префиксные коды, неравенство Крафта—Макмиллана и жадный алгоритм Хаффмана. К концу урока вы построите оптимальный код вручную и проверите его на пределе сжатия.
Что значит закодировать сообщение?#
Пусть источник выдаёт символы алфавита . Код — правило, которое каждому символу ставит в соответствие кодовое слово: цепочку нулей и единиц. Самый простой вариант — равномерный код: , , , , все слова по два бита. Разбить длинную цепочку на слова элементарно — режем по два бита, и каждому кусочку однозначно соответствует символ. На символов равномерный код тратит бит на символ: для шести символов это три бита — восемь возможных комбинаций, из которых хватает шести, две пустуют — платим за простоту.
Экономия на частотах — не мелочь. В живых текстах буквы распределены отнюдь не поровну: в русском тексте «о» и «е» занимают добрую треть всех букв, а «ъ» и «э» — доли процента. Архиваторы этим питаются: внутри форматов ZIP и gzip код Хаффмана трудится как часть алгоритма DEFLATE, JPEG кодирует им коэффициенты картинки, а MP3 — спектральные данные. Один и тот же жадный алгоритм с 1952 года экономит место в файловых архивах и в фотографии.
Экономия живёт в неравномерности: если встречается в половине сообщений, короткое слово для неё окупит длинные слова для редких букв. Но с разной длиной приходит беда. Возьмём код и цепочку . Она читается двумя способами: как целиком и как с последующим . Приёмник не восстановит сообщение, даже зная код идеально: код неоднозначно декодируем — брак, не подлежащий починке на стороне приёмника.
Почему префиксный код декодируется на лету?#
Префиксный код — код, в котором ни одно кодовое слово не является началом (префиксом) другого. В наборе ни одно слово не начинается с другого: ноль никогда не открывает десятку, десятка — сотню с единицей. Читаем цепочку слева направо, и как только накопленное совпало со словом — символ определён однозначно, следующий символ начинается с чистого листа. Никаких пауз, никаких возвратов назад; такое декодирование — работа для конечного автомата с двумя-тремя состояниями.
Префиксность имеет наглядную геометрию — кодовое дерево. Каждый бит — выбор ветви: ноль влево, единица вправо; кодовое слово — путь от корня. Требование префиксности означает: слова сидят только в листьях, ни одно не лежит на пути к другому. Именно поэтому прочтение всегда останавливается вовремя. Строить и обходить такие структуры учит урок о деревьях и алгоритмах, здесь же дерево — рабочая картинка, а не предмет изучения.
Что запрещает неравенство Крафта—Макмиллана?#
Какие наборы длин слов вообще возможны? Интуиция подсказывает: слишком много коротких слов разом — не выйдет, дерево не резиновое. Точная формулировка:
Смысл простой: двоичная ёмкость делится пополам с каждым битом. Слово длины 2 — это одна четверть всего пространства цепочек, слово длины 3 — одна восьмая. Складываем вклады всех слов — должно остаться не больше целого. Проверим на полном коде :
Равенство означает полноту: добавить пятое слово, не разрушив префиксность, невозможно. А вот у набора длин (код ) сумма — есть запас, и слово добавимо. Мини-тренировка на полминуты: код даёт — запас есть, добавляем и и дотягиваемся до единицы. А пара уже исчерпала ёмкость дерева — третье слово к ней не пристроить в принципе.
Теорема Макмиллана добавляет неожиданное: неравенство обязано выполняться у любого однозначно декодируемого кода, даже не префиксного. А теорема Крафта — обратное: если длины прошли проверку, существует префиксный код с ровно этими длинами. Вместе выходит, что префиксные коды ничего не теряют: по длинам они не хуже любых однозначных, а декодируются проще. Отсюда и привычка всей теории: заниматься префиксными.
Как построить код Хаффмана по шагам?#
Идея: частым символам — короткие слова, редким — длинные. Алгоритм Хаффмана (1952) реализует её жадно: берём два самых редких символа (или узла), сливаем их в новый узел с суммарной частотой, возвращаем в список и повторяем, пока не останется один корень. Потом развешиваем по левым рёбрам нули, по правым единицы — и слова готовы. Прогоним на шести символах с частотами из сотни: — 45, — 13, — 12, — 16, — 9, — 5.
| Символ | Частота из 100 | Код | Длина | Вклад $f \cdot l$ |
|---|---|---|---|---|
| 45 | 0 | 1 | 45 | |
| 13 | 101 | 3 | 39 | |
| 12 | 100 | 3 | 36 | |
| 16 | 111 | 3 | 48 | |
| 9 | 1101 | 4 | 36 | |
| 5 | 1100 | 4 | 20 |
Деталь, о которую спотыкаются на контрольных: при равных весах порядок слияний неоднозначен, и коды двух прогонов могут отличаться словами. Это нормально: все варианты оптимальны одновременно — сумма вкладов одинакова, различаются лишь метки рёбер. На экзамене достаточно показать корректное дерево и посчитать среднюю длину; совпадать с ответом соседа должен не код, а число .
Проверка по Крафту: — код полный, длиннее и экономнее уже не бывает при этих частотах. Почему жадность не подводит: в оптимальном коде два самых редких символа обязаны сидеть на самой глубине и по соседству — иначе поменяем их местами с более глубокими листьями и улучшим код. Слияние пары просто фиксирует это обязательство, после чего задача уменьшается на один символ. Индукция заканчивает доказательство. Со списком, организованным в кучу, алгоритм работает за ; что стоит за такой записью — урок о сложности алгоритмов.
Куда упирается сжатие: энтропия#
Есть нижний предел, который не перепрыгнет никакой код. Энтропия распределения измеряет среднюю неожиданность символа:
Для любого однозначно декодируемого кода средняя длина не меньше энтропии: . В нашем примере частоты дают вероятности , и бита. Хаффман выдал — зазор в две сотых бита: до предела почти дотянулись, а дальше некуда.
Масштабируем на файл из 10 000 символов. Равномерный код: 30 000 бит. Хаффман: 22 400 бит. Энтропийный предел: около 22 200 бит. Побуквенным кодированием ниже не уйти — остаются блоки: кодировать пары и тройки символов как один знак нового алфавита, зазор до энтропии делится на длину блока. А если символы источника коррелируют (после «ч» в русском языке почти наверняка пойдёт гласная), энтропия блоков ещё ниже суммы энтропий букв.
Сжатие — половина дела кодирования. Вторая половина — защита от помех: туда, где биты теряются и портятся, избыточность добавляют сознательно, чтобы приёмник чинил ошибки. Как устроена такая арифметика — в парном уроке про коды Хэмминга; сжатие и помехоустойчивость — две стороны одного баланса между экономией и надёжностью.
- Равномерный код тратит бит на символ; неравномерный экономит, но требует разделения слов
- Префиксность — достаточное условие однозначного декодирования: слова — листья дерева, чтение останавливается вовремя
- Крафт—Макмиллан: — обязательное условие для любых однозначных кодов; при выполнении префиксный код с этими длинами существует
- Хаффман: слияние двух самых редких, средняя длина оптимальна среди побуквенных префиксных кодов
- Энтропия — предел сжатия: , зазор сокращают блочным кодированием
Следующий шаг логичен: префиксные коды экономят биты, а помехоустойчивые — платят ими осознанно. Открывайте коды Хэмминга и посмотрите, как три контрольных бита чинят один сбитый. Практика по смежным темам — задачи по комбинаторике и тренажёр по графам; деревья и их обходы повторяются по шпаргалке по графам и алгоритмам.
Код . Что показывает проверка неравенства Крафта?
Цепочка 1100111 пришла кодом (символы соответственно). Что было передано?
У источника два символа с вероятностями 0,9 и 0,1. Энтропия бита, а код Хаффмана даёт среднюю длину ровно 1 бит. Почему нет противоречия?
Частые вопросы
Чем префиксный код отличается от однозначно декодируемого?
Префиксность — достаточное условие однозначности: слова-листья читаются мгновенно слева направо. Однозначность шире: код из двух слов {0, 01} не префиксный, но каждая цепочка расшифровывается единственным образом. Теорема Крафта—Макмиллана уравнивает классы по длинам: префиксный код существует тогда и только тогда, когда существует однозначный с теми же длинами. На практике выбирают префиксные — они декодируют без задержки.
Почему в азбуке Морзе не возникает путаницы?
Потому что кроме точек и тире есть паузы: короткая между элементами одной буквы и длинная между буквами. Именно пауза-разделитель делает код однозначным, хотя сама азбука не префиксная: точка E — начало кода большинства букв. Цена — время: пауза занимает заметную долю эфира, тогда как префиксный код передаёт биты сплошным потоком без служебных знаков.
Что делать, если неравенство Крафта нарушено?
Такой набор длин невозможен ни для какого однозначно декодируемого кода — приёмник не сможет восстановить сообщения, где-то ветвление дерева оборвётся посередине слова. Выход один: удлинить какие-то слова или сократить алфавит. После починки удобнее пересобрать код алгоритмом Хаффмана: он выдаст допустимые длины и заодно оптимизирует среднюю.
Код Хаффмана всегда даёт максимально возможное сжатие?
Среди побуквенных префиксных кодов для заданного распределения частот — да, это теорема. Но предел энтропии может быть ниже: побуквенный код тратит целые биты на символ, а энтропия дробная, зазор достигает бита. Кодирование блоками по несколько символов делит зазор на длину блока, а арифметическое кодирование приближается к энтропии практически вплотную.
Готовитесь к контрольной?
Чеклист тем по «Дискретка»: что вы уже умеете, что повторить и в каком порядке.
Открыть чеклист предмета →
Проверьте себя в бою
Босс-экзамен по «Дискретка»: квизы всех уроков плюс бесконечный поток сгенерированных задач. Каждая попытка — новый расклад.
Начать босс-экзамен →