Файл: Технологии программирования (Возникновение теории кодирования).pdf
Добавлен: 25.04.2023
Просмотров: 553
Скачиваний: 1
СОДЕРЖАНИЕ
1. Сущность кодирования данных в информационных системах.
1.1 Возникновение теории кодирования
1.3 Понятие кодирования информации
2. Основные методы кодирования данных
2.1.1 Код класса Fixed + Variable
2.1.2 Код класса Variable + Variable
2.3.2 Алгоритм построения бинарного кода Хаффмана
2.3.4 Пример выполнения алгоритма
2.3.5 Корректность алгоритма Хаффмана
2.5 Сравнение алгоритмов Хафмана и Шеннона – Фано
2.7 Преобразование Барроуза-Уилера
2. Основные методы кодирования данных
2.1 Кодирование целых чисел
Рассмотрим семейство методов кодирования, не учитывающих вероятности появления символов источника. Поскольку все символы алфавита источника можно пронумеровать, то будем считать, что алфавит источника состоит из целых чисел.
Каждому целому числу из определенного диапазона ставится в соответствие свое кодовое слово. Поэтому эту группу методов также называют представлением целых чисел (representation of integers).
Основная идея кодирования целых чисел: отдельно кодировать порядок значения элемента («экспоненту» ) и отдельно – значащие цифры значения («мантиссу» i).
Значащие цифры мантиссы начинаются со старшей ненулевой цифры, порядок числа определяется позицией старшей ненулевой цифры в двоичной записи числа.
Как и при десятичной записи, порядок равен числу цифр в записи числа без предшествующих незначащих нулей.
Пример:
Двоичное число 000001101
Порядок равен 4, мантисса – 1101
Рассмотрим две группы методов кодирования целых чисел. Условно их можно обозначить так:
- Fixed + Variable (фиксированная длина порядка + переменная длина мантиссы)
- Variable + Variable (переменная длина порядка + переменная длина мантиссы)
В кодах класса Fixed + Variable под запись значения порядка числа отводится фиксированное количество бит, а значение порядка числа определяет, сколько бит потребуется под запись мантиссы.
Для кодирования целого числа необходимо произвести с числом две операции:
- определение порядка числа
- выделение бит мантиссы
Можно также хранить в памяти заранее построенную таблицу кодовых слов и по ней получать код числа.
2.1.1 Код класса Fixed + Variable
Пусть R = 15 – количество бит исходного числа.
Отведем E = 4 бита под порядок, т.к. R ≤ 24.
При записи мантиссы можно сэкономить 1 бит: не писать первую единицу, т.к. это всегда будет только единица.
Таким образом, количество бит мантиссы меньше на один бит, чем значение порядка числа.
Таблица 1
Коды чисел класса Fixed + Variable
|
Число |
Двоичное представление |
Кодовое слово |
Длина кодового слова |
|
0 1 |
000000000000000 000000000000001 |
0000 0001 |
4 |
|
2 3 |
000000000000010 000000000000011 |
0010 0 0010 1 |
5 |
|
4 5 6 7 |
000000000000100 000000000000101 000000000000110 000000000000111 |
0011 00 0011 01 0011 10 0011 11 |
6 |
|
8 9 10 … 15 |
000000000001000 000000000001001 000000000001010 … 000000000001111 |
0100 000 0100 001 0100 010 … 0100 111 |
7 |
|
16 17 … |
000000000010000 000000000010001 … |
0101 0000 0101 0001 … |
8 |
2.1.2 Код класса Variable + Variable
В качестве кода числа берется двоичная последовательность, построенная следующим образом: несколько нулей (количество нулей равно значению порядка числа), затем мантисса переменной длины.
Таблица 2
Коды чисел класса Variable + Variable
|
Число |
Двоичное представление |
Кодовое слово |
Длина кодового слова |
|
0 1 |
00000000000 00000000001 |
00 01 |
1 2 |
|
2 3 |
00000000010 00000000011 |
00 10 00 11 |
4 |
|
4 5 6 7 |
00000000100 00000000101 00000000110 00000000111 |
000 100 000 101 000 110 000 111 |
6 |
|
8 9 10 |
00000001000 00000001001 00000001010 |
0100 000 0100 001 0100 010 |
8 |
Если в рассмотренном выше коде исключить кодовое слово для нуля, то можно уменьшить длины кодовых слов на 1 бит, убрав первый нуль во всех кодовых словах. Таким образом строится гамма-код Элиаса (γ-код Элиаса).
Таблица 3
γ-код Элиаса
|
Число |
Кодовое слово |
Длина кодового слова |
|
1 |
1 |
1 |
|
2 3 |
0 10 0 11 |
3 |
|
4 5 6 7 |
00 100 00 101 00 110 00 111 |
5 |
|
8 9 10 |
000 1000 000 1001 00 1010 |
7 |
Другим примером кода класса Variable + Variable является омега-код Элиаса (ω-код Элиаса).
В нем первое значение (кодовое слово для единицы) задается отдельно. Другие кодовые слова состоят из последовательности групп длиной L1 L2 …Lm , начинающихся с единицы.
Конец всей последовательности задается нулевым битом.
Длина первой группы составляет 2 бита, длина каждой следующей группы равна двоичному значению битов предыдущей группы плюс 1.
Значение битов последней группы является итоговым значением всей последовательности групп, т.е. первые m-1 групп служат лишь для указания длины последней группы, которая содержит собственно мантиссу числа.
Таблица 4
ω-код Элиаса
|
Число |
Кодовое слово |
Длина кодового слова |
|
1 2 3 |
0 10 0 11 0 |
1 3 3 |
|
4 5 6 7 |
10 100 0 10 101 0 10 110 0 10 111 0 |
6 6 6 6 |
|
8 9 .. 15 |
11 1000 0 11 1001 0 .. 11 1111 0 |
7 7 .. 7 |
|
16 17 .. 31 |
10 100 10000 0 10 100 10001 0 .. 10 100 11111 0 |
11 11 .. 11 |
|
32 |
10 101 100000 0 |
12 |
В омега-коде Элиаса (P. Elias):
При кодировании формируется сначала последняя группа, затем предпоследняя и т.д., пока процесс не будет завершен.
При декодировании, наоборот, сначала считывается первая группа, по значению ее битов определяется длина следующей группы, или итоговое значение числа, если следующая группа – 0.
- Рассмотренные типы кодов могут быть эффективны в следующих случаях:
- Вероятности чисел убывают с ростом значений элементов и их распределение близко к такому: P(x) ≥ P(x+1), при любом x, т.е. маленькие числа встречаются чаще, чем большие.
- Диапазон значений входных элементов не ограничен или неизвестен.
Например, при кодировании 32-битовых чисел реально большинство чисел маленькие, но могут быть и большие. - При использовании в составе других схем кодирования, например, кодировании длин серий.
2.2 Кодирование длин серий
Метод кодирования длин серий (RLE), предложенный П. Элиасом (P.Elias), при построении использует коды целых чисел. Входной поток для кодирования рассматривается как последовательность из нулей и единиц.
Идея кодирования заключается в том, чтобы кодировать последовательности одинаковых элементов (например, нулей) как целые числа, указывающие количество элементов в этой последовательности.
Последовательность одинаковых элементов называется серией, количество элементов в ней – длиной серии.
2.2.1 Пример кодирования длин серий
Входную последовательность (31 бит) можно разбить на серии, а затем закодировать их длины.
000000 1 00000 1 0000000 1 1 00000000 1
Длины серий нулей: 6 5 7 0 8
Используем, например, γ-код Элиаса.
Поскольку в γ-коде Элиаса нет кодового слова для нуля,то будем кодировать длину серии +1: 65708 ⇒ 76819
7 6 8 1 9 ⇒ 00111 00110 0001000 1 0001001
Длина полученной кодовой последовательности 25 бит.
Метод длин серий актуален для кодирования данных, в которых есть длинные последовательности одинаковых бит. В нашем примере, если P(0)>>P(1).
2.3 Код Хафмана
Код Хаффмана (англ. Huffman's algorithm) — алгоритм оптимального префиксного кодирования алфавита. Разработан в 1952 году аспирантом Массачусетского технологического института Дэвидом Хаффманом при написании им курсовой работы. [7]
Кодирование Хаффмана широко применяется при сжатии данных, в том числе при сжатии фото- и видеоизображений (JPEG, MPEG), в популярных архиваторах (PKZIP, LZH и др.), в протоколах передачи данных HTTP (Deflate), MNP5 и MNP7 и других. [3]
В 2013 году была предложена модификация алгоритма Хаффмана, позволяющая кодировать символы дробным количеством бит — ANS. На базе данной модификации реализованы алгоритмы сжатия Zstandard (Zstd, Facebook, 2015—2016) и LZFSE[fr] (Apple, OS X 10.11, iOS 9, 2016).
2.3.1 Определение
Пусть A={a1,a2,…,an} — алфавит из n различных символов, W={w1,w2,…,wn} — соответствующий ему набор положительных целых весов. Тогда набор бинарных кодов C={c1,c2,…,cn}, где ci является кодом для символа ai, такой, что:
ci не является префиксом для cj, при i≠j,
cумма ∑i∈[1,n]wi⋅|ci| минимальна (|ci| — длина кода ci),
называется кодом Хаффмана.[7]
2.3.2 Алгоритм построения бинарного кода Хаффмана
Построение кода Хаффмана сводится к построению соответствующего бинарного дерева по следующему алгоритму:
- Составим список кодируемых символов, при этом будем рассматривать один символ как дерево, состоящее из одного элемента c весом, равным частоте появления символа в строке.
- Из списка выберем два узла с наименьшим весом.
- Сформируем новый узел с весом, равным сумме весов выбранных узлов, и присоединим к нему два выбранных узла в качестве детей.
- Добавим к списку только что сформированный узел вместо двух объединенных узлов.
- Если в списке больше одного узла, то повторим пункты со второго по пятый.
2.3.3 Время работы
Если сортировать элементы после каждого суммирования или использовать приоритетную очередь, то алгоритм будет работать за время O(N log N).Такую асимптотику можно улучшить до O(N), используя обычные массивы.
2.3.4 Пример выполнения алгоритма
Закодируем слово abracadabra. Тогда алфавит будет A={a,b,r,c,d} а набор весов (частота появления символов алфавита в кодируемом слове) W={5,2,2,1,1}. Графическое представление можно посмотреть в приложении на рисунке 4.