Пример: Глобальная сеть INTERNET
Я ищу:
На главную  |  Добавить в избранное  

Главная/

Программирование, базы данных. /

Сжатие данных

Документ 1 | Документ 2 | Документ 3 | Документ 4

←предыдущая следующая→
1 2 3 4 5 6 7 

ниже листьев, поэтому  значения индексов

между 1 и maxchar включительно будут применены для обозначения ссылок на внут-

ренние узлы, когда как значения индексов между  maxchar + 1 и  2 * maxchar + 1

включительно - ссылок на листья. Заметим что корень дерева всегда  находится в

1-ой ячейке и имеет неопределенного родителя. Cоотвествующая листу буква может

быть найдена вычитанием maxchar + 1 из его индекса.

    Если окончание текста источника может быть обнаружено из его контекста, то

коды исходного алфавита все находятся в интервале codetype, а максимально воз-

можное в этом тексте значение кода будет maxchar. В противном случае, интервал

codetype  должен быть  расширен на один код  для описания специального символа

"конец файла". Это означает, что maxchar будет на 1 больше значения максималь-

ного кода символа исходного текста.

    Следующая процедура инициализирует  дерево кодов. Здесь строится сбаланси-

рованное дерево кодов, но на самом деле, каждое начальное дерево будет удовле-

творительным до тех пор, пока оно же используется и для сжатия и для разверты-

вания.

procedure initialize;

var

  i: downindex;

  j: upindex;

begin

  for i := 2 to twicemax do

    up[i] := i div 2;

  for j := 1 to maxchar do begin

    left[j] := 2 * j;

    right[j] := 2 * j + 1;

  end

end { initialize };

    После того, как каждая буква сжата ( развернута ) с помощью текущей версии

дерева  кодов, оно  должно быть  расширено вокруг  кода этой буквы. Реализация

этой операции показана  в следующей процедуре, использующей  расширение снизу-

вверх:

procedure splay( plain: codetype );

var

  c, d: upindex    { пары узлов для полуобоpота };

  a, b: downindex  { вpащаемые наследники узлов };

begin

  a := plain + succmax;

  repeat           { обход снизу вверх получередуемого дерева }

    c := up[a];

    if c # root then begin { оставляемая пара }

      d := up[c];

      { перемена местами наследников пары }

      b := left[d];

      if c = b then begin b := right[d];

                          right[d] := a;

      end else            left[d] := a;

      if a = left[c] then left[c] := b;

      else                right[c] := b;

      up[a] := d;

      up[b] := c;

      a := d;

    end else a := c         { управление в конце нечетным узлом };

  until a = root;

end { splay };

    Чтобы сжать букву исходного текста  ее нужно закодировать, используя дере-

во кодов, а затем передать. Поскольку процесс кодирования производится при об-

ходе дерева  от листа  к корню, то биты кода записываются  в обpатном порядке.

Для изменения порядка следования битов процедура compress пpименяет свой стек,

биты из которого достаются по одному и передаются процедуре transmit.

procedure compress( plain: codetype );

var

  a: downindex;

  sp: 1..succmax;

  stack: array[upindex] of bit;

begin

  { кодирование }

  a := plain + succmax;

  sp := 1;

  repeat { обход снизу вверх дерева и помещение в стек битов }

    stack[sp] := ord( right[up[a]] = a );

    sp := sp + 1;

    a := up[a];

  until a = root;

  repeat { transmit }

    sp := sp - 1;

    transmit( stack[sp] );

  until sp = 1;

  splay( plain );

end { compress };

    Для развертывания буквы необходимо читать из архива следующие друг за дру-

гом биты с помощью функции receive. Каждый прочитанный  бит задает один шаг на

маршруте обхода дерева от корня к листу, определяющем разворачиваемую букву.

function expand: codetype;

var

  a: downindex;

begin

  a := root;

  repeat { один раз для каждого бита на маршруте }

    if receive = 0 then a := left[a]

    else                a := rignt[a];

  until a > maxchar;

  splay( a - succmax );

  expand := a - succmax;

end { expand };

    Процедуры, управляющие сжатием и развертыванием, просты и представляют со-

бой вызов процедуры  initialize, за которым следует вызов либо  compress, либо

expand для каждой обрабатываемой буквы.

         Характеристика алгоритма расширяемого префикса.

    На практике, расширяемые  деревья, на  которых основываются коды префикса,

хоть  и не являются оптимальными, но обладают  некоторыми полезными качествами.

Прежде всего  это скорость выполнения, простой  программный  код  и компактные

структуры данных. Для алгоритма расширяемого префикса требуется только 3 мас-

сива, в то время как для Л-алгоритма Уитерса, вычисляющего оптимальный адапти-

рованный код префикса, -  11 массивов . Предположим, что для обозначения

множества символов исходного текста используется 8 бит на символ, а конец фай-

ла определяется символом, находящимся вне 8-битового предела, maxchar = 256, и

все элементы массива могут содержать от 9 до 10 битов ( 2 байта на большинстве

машин)(3). Неизменные запросы памяти у алгоритма расширяемого префикса состав

ляют приблизительно 9.7К битов (2К байтов на большинстве машин). Подобный под-

ход к хранению массивов  в  Л-алгоритме требует около 57К битов (10К байтов на

большинстве машин ).

    Другие широко применяемые алгоритмы сжатия требуют  еще большего простран-

ства, например, Уэлч советует для реализации метода  Зива-Лемпела исполь-

зовать хеш-таблицу из 4096 элементов по 20 битов каждый, что в итоге составля-

ет уже  82К битов ( 12К байтов на большинстве машин ). Широко используемая ко-

манда сжатия в системе ЮНИКС Беркли применяет код  Зива-Лемпела, основанный на таблице  в  64К элементов по крайней мере в  24 бита каждый, что  в итоге дает

1572К битов ( 196К байтов на большинстве машин ).

    В таблице I показано как Л-алгоритм Уиттера и алгоритм расширяющегося пре-

фикса характеризуются на множестве разнообразных тестовых данных. Во всех слу-

чаях был применен алфавит из  256 отдельных символов, расширенный дополнитель

ным знаком конца файла. Для всех файлов, результат работы Л-алгоритма находит-

ся в пределах 5% от H  и обычно составляет 2% от H . Результат работы алгорит-

ма расширяющегося префикса никогда не превышает H  больше, чем на 20%, а иног

да бывает много меньше H .

    Тестовые данные включают программу на Си (файл 1), две программы на Паска-

ле (файлы 2 и 3) и произвольный текстовый файл (файл 4). Все текстовые файлы

используют множество символов кода ASCII  с табуляцией, заменяющей группы

из 8 пробелов в начале, и все пробелы в конце строк. Для  всех этих файлов  Л-

алгоритм достигает результатов, составляющих примерно 60% от размеров исходно-

го текста, а алгоритм расширения - 70%. Это самый худший случай сжатия, наблю-

даемый при сравнении алгоритмов.

    Два объектых файла М68000 были  сжаты ( файлы 5 и 6 ) также  хорошо, как и

файлы  вывода  TEX в формате  .DVI ( файл 7 ). Они имеют меньшую избыточность

←предыдущая следующая→
1 2 3 4 5 6 7 


Copyright © 2005—2007 «RefStore.Ru»