Оптимальный префиксный код с длиной кодового слова не более L бит — различия между версиями
Строка 6: | Строка 6: | ||
==Пример.== | ==Пример.== | ||
− | Данный алгоритм бывает полезен, когда нам нужно ограничить максимальную длину кодового слова, а при использовании алгоритма Хаффмана самому редко встречающемуся символу соответствует слишком длинное кодовое слово. Например, пусть дан алфавит из 5 символов <tex>A=\{A,B,C, C, D\}</tex>, а частоты символов являются степенями двойки: <tex>P=\{1,2,4, 8, 16\}</tex>. Тогда классический код | + | Данный алгоритм бывает полезен, когда нам нужно ограничить максимальную длину кодового слова, а при использовании алгоритма Хаффмана самому редко встречающемуся символу соответствует слишком длинное кодовое слово. Например, пусть дан алфавит из <tex>5</tex> символов <tex>A=\{A,B,C, C, D\}</tex>, а частоты символов являются степенями двойки: <tex>P=\{1,2,4, 8, 16\}</tex>. Тогда классический код Хаффмана будет выглядеть следующим образом: |
{| class="wikitable" | {| class="wikitable" | ||
Строка 40: | Строка 40: | ||
Важно заметить следующий факт. В худшем случае все кодовые слова будут иметь длину <tex>L</tex> бит. Тогда мы можем закодировать <tex> 2^L </tex> символов. Таким образом, нельзя получить описанный выше код, если <tex> n > 2^L </tex>. | Важно заметить следующий факт. В худшем случае все кодовые слова будут иметь длину <tex>L</tex> бит. Тогда мы можем закодировать <tex> 2^L </tex> символов. Таким образом, нельзя получить описанный выше код, если <tex> n > 2^L </tex>. | ||
− | == Сведение задачи о | + | == Сведение задачи о генерации оптимального префиксного кода с длиной кодового слова не более L бит к задаче о рюкзаке == |
− | Пусть <tex>L</tex> — ограничение на длину кодового слова, а <tex>P=\{p_{1},p_{2}, | + | Пусть <tex>L</tex> — ограничение на длину кодового слова, а <tex>P=\{p_{1},p_{2},\dots,p_{n}\}</tex> — частоты символов алфавита. Алгоритм генерации кода будет следующим: |
− | |||
# Для каждого символа создадим <tex>L</tex> предметов ценностью <tex>2^{-1}\dots2^{-L}</tex>, каждый из которых имеет вес <tex>p_{i}</tex>. | # Для каждого символа создадим <tex>L</tex> предметов ценностью <tex>2^{-1}\dots2^{-L}</tex>, каждый из которых имеет вес <tex>p_{i}</tex>. | ||
# С помощью задачи о рюкзаке выберем набор предметов суммарной ценностью <tex>n - 1</tex> (<tex>n</tex> — размер алфавита) с минимальным суммарным весом. | # С помощью задачи о рюкзаке выберем набор предметов суммарной ценностью <tex>n - 1</tex> (<tex>n</tex> — размер алфавита) с минимальным суммарным весом. | ||
− | # Посчитаем массив <tex>H=\{h_{1},h_{2}, | + | # Посчитаем массив <tex>H=\{h_{1},h_{2},\dots,h_{n}\}</tex>, где <tex>h_{i}</tex> — количество предметов ценностью <tex>p_{i}</tex>, которые попали в наш набор. |
При этом <tex>h_{i}</tex> — это длина кодового слова для <tex>i</tex>-го символа. Зная длины кодовых слов, легко восстановить и сам код. | При этом <tex>h_{i}</tex> — это длина кодового слова для <tex>i</tex>-го символа. Зная длины кодовых слов, легко восстановить и сам код. | ||
Строка 55: | Строка 54: | ||
== Восстановление ответа. == | == Восстановление ответа. == | ||
+ | Рассмотрим процедуру восстановления ответа по заданному алфавиту и известным длинам кодовых слов. | ||
# Отсортируем все символы по возрастанию длины кодового слова, которое им соответствует, а при равенстве длин — в алфавитном порядке. | # Отсортируем все символы по возрастанию длины кодового слова, которое им соответствует, а при равенстве длин — в алфавитном порядке. | ||
# Первому символу сопоставим код, состоящий из нулей, соответствующей длины. | # Первому символу сопоставим код, состоящий из нулей, соответствующей длины. | ||
Строка 106: | Строка 106: | ||
==Источники информации== | ==Источники информации== | ||
− | *[http://en.wikipedia.org/wiki/Package-merge_algorithm Wikipedia | + | *[http://en.wikipedia.org/wiki/Package-merge_algorithm Wikipedia — Package-merge algorithm] |
− | *[http://en.wikipedia.org/wiki/Canonical_Huffman_code Wikipedia | + | *[http://en.wikipedia.org/wiki/Canonical_Huffman_code Wikipedia — Canonical Huffman code] |
[[Категория: Дискретная математика и алгоритмы]] | [[Категория: Дискретная математика и алгоритмы]] | ||
[[Категория: Алгоритмы сжатия ]] | [[Категория: Алгоритмы сжатия ]] |
Версия 20:05, 9 января 2015
Оптимальный префиксный код с длиной кодового слова не более L бит — это код, обладающий следующими свойствами:
- является оптимальным префиксным кодом
- длина кодового слова не превышает заданной константы
Здесь будет приведен алгоритм, решающий эту задачу за время задаче о рюкзаке.
, где — максимальная длина кодового слова, — размер алфавита, c помощью сведения задачи кСодержание
- 1 Пример.
- 2 Сведение задачи о генерации оптимального префиксного кода с длиной кодового слова не более L бит к задаче о рюкзаке
- 3 Восстановление ответа.
- 4 Пример работы алгоритма генерации оптимального префиксного кода с длиной кодового слова не более L бит
- 5 Пример восстановления ответа.
- 6 См. также
- 7 Источники информации
Пример.
Данный алгоритм бывает полезен, когда нам нужно ограничить максимальную длину кодового слова, а при использовании алгоритма Хаффмана самому редко встречающемуся символу соответствует слишком длинное кодовое слово. Например, пусть дан алфавит из
символов , а частоты символов являются степенями двойки: . Тогда классический код Хаффмана будет выглядеть следующим образом:Символ | Частота | Код |
---|---|---|
A | 1 | 1111 |
B | 2 | 1110 |
C | 4 | 110 |
D | 8 | 10 |
E | 16 | 0 |
Самое длинное кодовое слово здесь имеет длину
. Пусть мы хотим, чтобы слова в нашем коде были не длиннее трех бит. Тогда алгоритм, который будет описан ниже, генерирует такой код:Символ | Частота | Код |
---|---|---|
A | 1 | 000 |
B | 2 | 001 |
C | 4 | 010 |
D | 8 | 011 |
E | 16 | 1 |
Важно заметить следующий факт. В худшем случае все кодовые слова будут иметь длину
бит. Тогда мы можем закодировать символов. Таким образом, нельзя получить описанный выше код, если .Сведение задачи о генерации оптимального префиксного кода с длиной кодового слова не более L бит к задаче о рюкзаке
Пусть
— ограничение на длину кодового слова, а — частоты символов алфавита. Алгоритм генерации кода будет следующим:- Для каждого символа создадим предметов ценностью , каждый из которых имеет вес .
- С помощью задачи о рюкзаке выберем набор предметов суммарной ценностью ( — размер алфавита) с минимальным суммарным весом.
- Посчитаем массив , где — количество предметов ценностью , которые попали в наш набор.
При этом
— это длина кодового слова для -го символа. Зная длины кодовых слов, легко восстановить и сам код.Из последнего утверждения и шага 2 легко заметить, что длина кодового слова, сгенерированного приведенным алгоритмом, действительно не превысит
. Это так, потому что мы создаем ровно L предметов веса (частота символа). А значит, если в худшем случае мы возьмем все предметы данного веса, то их количество не превысит . Обратите внимание, что одинаковые частоты у разных символов считаются разными,т.е. если , то при подсчете количества предметов заданного веса мы считаем предеметы с частотой и предметы с частотой отдельно.Оптимальность же кода следует из оптимальности решения задачи о рюкзаке. Действительно, частота символа - это вес предеметов, соответствующих ему. Значит, чем чаще символ встречается в тексте, тем реже он будет попадать в наш рюкзак (будет выгоднее брать предметы аналогичной ценности, но меньшего веса, соответствующие более редким символам), а значит, его код будет короче.
Восстановление ответа.
Рассмотрим процедуру восстановления ответа по заданному алфавиту и известным длинам кодовых слов.
- Отсортируем все символы по возрастанию длины кодового слова, которое им соответствует, а при равенстве длин — в алфавитном порядке.
- Первому символу сопоставим код, состоящий из нулей, соответствующей длины.
- Каждому следующему символу сопоставим следующее двоичное число. При этом если его длина меньше необходимой, то допишем нули справа.
Заметим, что при генерации каждого следующего кодового слова, в качестве его префикса выступает последовательность, лексикографически большая, чем предыдущее кодовое слово (т.к. мы берем следующее двоичное число), а значит ни для каких двух кодовых слов одно не может быть префиксом другого. Т.е. код, сгенерированный таким образом является префиксным.
Пример работы алгоритма генерации оптимального префиксного кода с длиной кодового слова не более L бит
Пусть
— алфавит из трех различных символов, — соответствующий ему набор частот. Пусть — ограничение на длину кодового слова.Сначала создадим необходимый набор предметов;
Символ | Частота | Предметы |
---|---|---|
Решим задачу о рюкзаке для заданного набора и выберем предметы суммарной ценностью
с минимальным суммарным весом. В нашем случае в оптимальный набор попадут следующие предметы:
Посчитаем массив
:
Итак, мы получили длины кодовых слов для символов. Осталось восстановить ответ.
Пример восстановления ответа.
Итак, у нас есть
— алфавит из различных символов, а также — соответсвующие длины кодовых слов. Отсортируем символы в соответсвии с этими длинами.Сопоставим первому символу код, состоящий из 1 нуля:
Сопоставим следующему символу следующее двоичное число. Т.к. длина кода увеличилась на один, то припишем справа ноль:
Сопоставим следующему символу следующее двоичное число.