Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Мясникова СИАОД.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
572.42 Кб
Скачать

Символ Код

А 010

B 100

C 000

D 111

Сообщение ABACCDA кодируется как 010100010000000111010. Однако такая кодировка была бы неэффективной, поскольку для каждого символа используются 3 бит, так что для кодировки всего сообщения требуется 21 бит. Предположим, что каждому символу назначен 2-битовый код:

Символ Код

А 00

B 01

C 10

D 11

Тогда кодировка сообщения была бы 00010010101100; требуется лишь 14 бит. Мы хотим найти код, который минимизирует длину закодированного сообщения.

Рассмотрим наш пример еще раз. Каждая из букв B и D появляется в сообщении только один раз, а буква A — три раза. Стало быть, если выбран код, в котором букве A назначена более короткая строка битов, чем буквам B и D, то длина закодированного сообщения будет меньше. Это происходит оттого, что короткий код (представляющий букву А) появляется более часто, чем длинный. В самом деле, коды могут быть назначены следующим образом:

Символ Частота Код

А 3 0

B 1 110

C 2 10

D 1 111

При использовании этого кода сообщение ABACCDA кодируется как 0110010101110, что требует лишь 13 бит. В очень длинных сообщениях, которые содержат символы, встречающиеся чрез­вычайно редко, экономия существенна. Обычно коды создаются не на основе частоты вхождения символов в отдельно взятом сообщении, а на основе их частоты во всем множестве сообще­ний. Для каждого сообщения используется один и тот же код. Например, если сообщения состоят из английских слов, могут использоваться известные данные о частоте появления символов алфавита в английском языке.

Отметьте, что если используются коды переменной длины, то код одного символа не должен совпадать с началом кода другого символа. Такое условие должно выполняться, если рас­кодирование происходит слева направо. Если бы код символа x—c(x) совпадал с началом кода символа y—c(y), то, когда встречается код c(x), неясно, является ли он кодом символа x или началом кода c (y).

В нашем случае битовая строка сообщения просматривается слева направо. Если первый бит равен 0, то это символ A; в противном случае это B, С или D и проверяется следующий бит. Если второй бит равен 0, то это символ C, иначе это B или D и надо проверить третий бит. Если он равен 0, значит это B, а если 1, то D. Как только распознан первый символ, процесс повторяется для нахождения второго символа, начиная со следующего бита.

Такая операция подсказывает метод реализации оптимальной схемы кодирования, если известны частоты появления каждого символа в сообщении. Находим два символа, появляющихся наименее часто. В нашем примере это B и D. Будем различать их по последнему биту кодов: 0—В, 1—D. Соединим эти символы в единый символ BD, появление которого означает, что это либо символ B, либо символ D. Частота появления этого нового символа равна сумме частот двух составляющих сим­волов. Стало быть, частота BD — 2. Теперь у нас есть три сим­вола: А (частота 3), C (частота 2) и BD (частота 2). Снова выберем два символа с наименьшей частотой, т. е. C и BD. Будем различать их по последнему биту кодов: 0 — С, 1 — BD. Затем два символа объединяются в один символ CBD с часто­той 4. К этому времени осталось только два символа — А и CBD. Они объединяются в один символ ACBD. Будем различать их по последнему биту кодов: 0 — А, 1 — CBD.

Символ ACBD содержит весь алфавит, ему присваивается в качестве кода пустая строка битов нулевой длины. Это озна­чает, что вначале раскодирования до момента проверки какого-либо бита известно, что этот символ содержится в ACBD. Двум символам, составляющим ACBD (А и CBD), присваиваются соответственно коды 0 и 1: если встречается 0, значит, закоди­рован символ A, а если 1, то это C, B или D. Аналогично двум символам, составляющим CBD (С и BD), назначаются соответ­ственно коды 10 и 11. Первый бит указывает, что символ входит в группу CBD, а второй позволяет отличить C и BD. Символам, составляющим BD (В и D), назначаются соответственно коды 110 и 111. Следуя этому процессу, символам, которые появля­ются в сообщении часто, присваиваются более короткие коды, чем тем, которые встречаются редко.

Операция объединения двух символов в один предполагает использование структуры бинарного дерева. Каждый лист пред­ставляет символ исходного алфавита. Каждый узел, не являю­щийся узлом, представляет соединение символов из листов — потомков данного узла. На рис. 1a приведено бинарное дерево, построенное с использованием предыдущего примера. Каждый узел содержит символ и его частоту. На рис. 1b показано бинарное дерево, построенное по данному методу для приведенной на рис. 1c таблицы символов алфавита и час­тот. Такие деревья называют деревьями Хаффмена, по имени изобретателя этого метода кодирования.

Как только дерево Хаффмена построено, код любого символа алфавита может быть определен просмотром дерева снизу вверх, начиная с листа, представляющего этот символ. Начальное зна­чение кода — пустая строка. Каждый раз, когда мы поднимаемся по левой ветви, к коду слева приписывается 0; каждый раз при подъеме по правой ветви к коду приписывается 1.

b

Символ Частота Код

Символ Частота Код

Символ Частота Код

A 15 111

B 6 0101

C 7 1101

A 12 011

B 25 10

C 4 01001

A 6 1100

B 1 01000

C 15 00

1c

Рис. 1. Деревья Хаффмена.

Отметьте, что дерево Хаффмена строго бинарное. Следова­тельно, если в алфавите n символов, то дерево Хаффмена (у которого n листьев) может быть представлено массивом узлов размером 2n-1. Поскольку размер памяти, требуемой под дерево, известен, она может быть выделена заранее. Отме­тим также, что дерево Хаффмена проходится от листьев к кор­ню. Отсюда следует, что не требуются поля LEFT и RIGHT, и для представления структуры дерева достаточно одного поля FTHER. Знак поля FTHER может использоваться для опреде­ления, является ли узел левым или правым сыном, а абсолютное значение поля служит указателем отца узла. Левый сын имеет отрицательное значение поля FTHER, а правый — положитель­ное.

Исходное сообщение (при наличии кодировки сообщения и дерева Хаффмена) может быть восстановлено следующим спо­собом. Начинаем с корня дерева. Каждый раз, когда встреча­ется 0, двигаемся по левой ветви, и каждый раз, когда встреча­ется 1, двигаемся по правой ветви. Повторяем этот процесс до тех пор, пока не дойдем до листа. Новый символ исходного со­общения есть символ, соответствующий этому листу. Проверьте, можете ли вы раскодировать строку 1110100010111011, используя дерево Хаффмена на рис. 1b.

  1. Сортировка. Методы вставок и обмена. Метод Шелла. Быстрая сортировка. Обменная поразрядная сортировка.