Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
OTI Lections2011.doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
1.74 Mб
Скачать

8Алгоритмы кодирования

8.1Алгоритм Шеннона (Фано)

Есть некоторые буквы:

(кодируем номером числа в двоичном виде)

H = 1/4 log 4 + 1/4 log 4 + 1/8 log 8 + 1/8 log 8 + 1/8 log 8 + 2 * 1/16 log 16 = 1 + 9/8 + 1/2 = 2, 625

Шаги алгоритма:

  1. Упорядочиваем по вероятности

  2. «Дихотомия»: разбиваем на части, вероятности которых одинаковы.

Т аким образом:

a1 00

a2 01

a3 100

a4 101

a5 110

a6 1110

a7 1111

lш = 21/7 = 3

Пример:

l = 3, lш = 12/5 = 2,4

H = 7/18 log 18/7 + 1/2 log 6 + 1/5 log 9 = 2,17

8.2Алгоритм Хаффмана

Заведомо дает меньшее решение, чем по Шеннону.

a 1 1/4

a2 1/4

a3 1/8

a4 1/8

a5 1/8

a6 1/16

a7 1/16

В этом алгоритме идут итерации, по сути это построение листьев бинарного дерева. (1, 2, 3, 4, 5, 6, 7) → (1, 2, 3, 4, 5, (6, 7)) → (1, 2, (3, 4), 5, (6, 7)) → (1, 2, (3, 4), (5, 6, 7)) → ((1, 2), (3, 4), (5, 6, 7)) → ((1, 2), (3, 4, 5, 6, 7))

Т

7

еперь, начиная с конца, строим бинарное дерево:

(6,7)

6

(5,6,7)

(3,4)

5

(3,4,5,6,7)

1

4

0

2

(1,2)

1

3

и код:

1 00

2 01

3 100

4 101

5 110

6 1110

7 1111

8.3Блочное кодирование

П оток из 0 и 1 будем интерпретировать как пары:

a 00 1/16 000

b 01 3/16 001

c 10 3/16 01

d 11 9/16 1

H (xx) = H(x) + H(x) = 2H(x) = 1,62

Хаффман: (a, b, c, d) → ((a, b), c, d) → (a, b, c), d)

l (xx) = ∑ pi li = 3/16 + 9/16 + 6/16 + 9/16 = 27/16

l(x) = 27/32 = 0, 844

a 000 1/64 00000

b 001 3/64 00001

c 010 3/64 00010

d 011 9/64 010

e 100 3/64 00011

f 101 9/64 001

g 110 9/64 001

h 111 27/64 1

(a, b, c, D, e, f, g, H) → ((a, b), c, D, e, f, g, H) → ((a, b), (c, e), D, f, g, H) → ((a, b, c, e), D, f, g, H) → ((a, b, c, e), (D, f), g, H) → ((a, b, c, e, g), (D, f), H) → ((a, b, c, D, e, f, g), H)

1

f

h

d

b

0

(a,b,c,d,e,f,g)

(d,f)

e

g

c

(a,b,c,e,g)

(c,e)

(a,b)

(a,b,c,e)

a

l = 5/64 + 15/64 + 15/64 + 15/64 +28/64 + 15/64 +27/64 +27/64 +27/64 = 50/64 +108/64 = 158/64 = 2,46875

Тогда:

X → l = 1

XX → l = 0,844

XXX → l = 0,823

H = 0,81

Пусть q (количество букв в кодируемом алфавите) = 2:

H(α) l(x)H(x) + 1

l(x)1H(x)l(x)

Hk(x) = H(xx….x) → (по т. Шеннона) lk(x)1Hk(x)lk(x)

Тогда Hk(x) = k H(x)

По определению lk(x) = k l(x) (правильнее l(x) = 1/k lk(x)). Получим: l(x)1/kH(x)l(x). Устремляем к бесконечности и делаем l(x) сколь угодно близким к H(x).

За такую точность приходится платить трудоемкостью алгоритмов кодирования (декодирования).

8.4Алгоритм арифметического кодирования

Его появление было связано с попыткой обойти сложности кодирования (декодирования) блочного алгоритма.

0 2/3

1 1/3

l(x) = 2/3 * 1 + 1/3 *1 = 1

H(x) = 2/3 log 3/2 + 1/3 log 3 = 0,918

  1. Разбиваем отрезок

½ ¾

0 0 2/3 1 1

2) Берем точку следующего вида: k/2m , k, m – натуральные, m – минимально возможное

3) Двоичная запись числа k

Этот метод используется при более сложных случаях:

0 1

00 01 10 11

000 001 010 011 100 101 110 111

0 8/27 4/9 16/27 2/3 22/27 8/9 26/27 1

a 000 1/4 01 8/27 01

b 001 3/8 011 4/27 110

c 010 2/4 1 4/27 000

d 011 5/8 101 2/27 100

e 100 3/4 11 4/27 001

f 101 7/8 111 2/27 101

g 110 15/16 1111 2/27 1110

h 111 31/32 11111 1/27 1111

Если k/2m и k/2p, то существуют варианты:

  1. Ставим маркеры-разделители (код не префиксный)

  2. p > m, число с 2m кодир. BIN(k), а с 2p - дописываем 0: 0BIN(k)

= 16/27 + 12/27 + 4/27 + 6/27 + 8/27 + 6/27 + 8/27 + 5/27 = 65/27 = lA(xxx)

lA(x) = 65/81 = 0,802 (т.к. код не префиксный)

Если добавим эффективный алгоритм построения маркера, то попадем между H(x) и 1.

(a, b, c, d, e, f, g, h)(a, b, c, d, e, f, (g, h))(a, b, c, (d, f), e, (g, h))(a, (b, g, h), c, e, (d, f))(a, (c, e), (d, f), (b, g, h))(a, (c, e), (d, f, b, g, h))((a, c, e), (b, f, d, g, h))

(d,f)

d

(d,f,b,g,h)

f

(b,g,h)

b

1

(a,c,e)

(g,h)

0

a

(c,e)

c

g

h

e

lбх(xxx) = 16/27 + 12/27 + 12/27 + 6/27 + 12/27 + 6/27 + 8/27 + 4/27 = 76/27 = 2,82

lбх(x) = 0,938

Алгоритм декодирования арифметического кода:

  1. α1, α2…αk – сообщение → (α1…αk) / 2k //

2.1) Поочередно восстанавливаем α1αk: α0 = φ(α1αk): 1. В какой части отрезка

[X,y];

2. Присваиваем α1… αn в

зависимости от отрезка.

2.2) (α0X) / |a – y| = α1 (новый) →2.1

На практике мы должны еще знать, дошли ли мы до маркера или нет.

Пример:

φ(d) = 101 → 5/8

  1. α0 = 5/8 → a1 = 0

  2. (5/8 – 0) / 2/3 = 15/16 = α0

  1. α0 = 15/16 → a2 = 1

  2. (15/16 – 2/3) / 1/3 = 39/48 = 13/16

  1. α0 = 13/16 → a3 = 1

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]