Алгоритмы LZ77 и LZ78 — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
Строка 17: Строка 17:
 
Это означает, что каждый символ можно однозначно определить, переместившись назад в буфере — даже если данный символ еще отсутствует в буфере на момент декодирования текущей пары ''длина-смещение''.
 
Это означает, что каждый символ можно однозначно определить, переместившись назад в буфере — даже если данный символ еще отсутствует в буфере на момент декодирования текущей пары ''длина-смещение''.
 
=== Описания алгоритма===
 
=== Описания алгоритма===
LZ77 использует "скользящее" по сообщению окно. Допустим на текущей итерации окно зафиксировано. С правой стороны окна наращиваем подстроку пока она есть в строке скользящее окно+наращиваемая строка и начинается в скользящем окне. После наращивания алгоритм выдает код состоящий из трех элементов:
+
LZ77 использует "скользящее" по сообщению окно. Допустим на текущей итерации окно зафиксировано. С правой стороны окна наращиваем подстроку пока она есть в строке скользящее окно+наращиваемая строка и начинается в скользящем окне. Назовем наращиваемую строку буфером. После наращивания алгоритм выдает код состоящий из трех элементов:
 
* смещение в окне;
 
* смещение в окне;
* длина подстроки;
+
* длина буфера;
* первый символ буфера, следующий за подстрокой.
+
* последний символ буфера.
В конце итерации алгоритм сдвигает окно на длину подстроки+1.
+
В конце итерации алгоритм сдвигает окно на длину равную длине буфера+1.
=== Пример  "kabababk"  ===
+
=== Пример  "kabababababz"  ===
 
{| border="1"  
 
{| border="1"  
  !Содержымое окна
+
  !Содержимое окна(длина равна 4)
  !Наращиваемая строка
+
  !Содержимое буфера
 
  !КОД
 
  !КОД
 
  |-
 
  |-
  |'.....'(  
+
  |'....'(  
  |Ячейка 2*2
+
  |'k'
  |Ячейка 3*2
+
  |<0,0,'k'>
 
  |-
 
  |-
  |Ячейка 1*3
+
  |'....'(
  |Ячейка 2*3
+
  |'a'
  |Ячейка 3*3
+
|<0,0,'a'>
 +
|-
 +
|'...a'
 +
|'b'
 +
|<0,0,'b'>
 +
|-
 +
|'..ab'
 +
|'aba'
 +
|<2,2,a>
 +
  |-
 +
|'baba'
 +
|'bababz'
 +
|<2,5,'z'>
 
  |}
 
  |}
 
              Поз.  Длина    Симв.
 
  ''mississippi ''    0      0      a
 
a ''bracadabra''    0      0      b
 
ab ''racadabra''    0      0      r
 
'''a'''br ''acadabra''    3      1      c
 
abr'''a'''c ''adabra''    2      1      d
 
'''abra'''cad ''abra''    7      4      abra
 
 
{{скрытый текст}}
 
<!--
 
Статья еще не содержит этой информации:
 
 
Even though all LZ77 algorithms work by definition on the same basic principle, they can vary widely in how they output their encoded data — what values are possible for lengths and distances, for example, and how length-distance pairs are distinguished from ''literals'' (single characters encoded as themselves, rather than as part of a length-distance pair.) A few examples:
 
* The algorithm illustrated in Lempel and Ziv’s original 1977 paper output all its data three values at a time: the length and distance of the longest match found in the buffer, and the literal which followed that match. If two successive characters in the input stream could only be encoded as literals, the length would be 0.
 
* In the [[PalmDoc]] format, a length-distance pair is always encoded by a two-byte sequence. Of the 16 bits that make up these two bytes, 11 bits go to encoding the distance, 3 go to encoding the length, and the remaining two are used to make sure the decoder can identify the first byte as the beginning of such a two-byte sequence.
 
* [[As of 2004]], the most popular LZ77 based compression method is called [[DEFLATE (algorithm)|DEFLATE]]; it combines LZ77 with [[Huffman coding]]. Literals, lengths, and a symbol to indicate the end of the current block of data are all placed together into one alphabet. Distances can be safely placed into a separate alphabet; since a distance only occurs just after a length, it cannot be mistaken for another kind of symbol or vice-versa.
 
-->
 
  
 
== LZ78 ==
 
== LZ78 ==

Версия 05:28, 29 октября 2010

LZ77 и LZ78 — алгоритмы сжатие без потерь, опубликованные в статьях Абрахама Лемпеля и Якоба Зива в 1977 и 1978 годах. Эти алгоритмы наиболее известные варианты в семействе LZ*, которое включает в себя также LZW, LZSS, LZMA и другие алгоритмы. Оба алгоритма относятся к словарным методам. LZ77 является алгоритмом со «скользящим окном», что эквивалентно неявному использованию словарного подхода, впервые предложенного в LZ78.

LZ77

Можно сказать, что алгоритмы семейства LZ* представляют собой более сложное обобщение простого и интуитивного способа сжатия данных, используемого в RLE.

Принципы работи алгоритма

Основная суть алгоритма - ето замена повторно вхождения строки ссылкою на одну из предыдущих позиций вхождения. Для етого используют метод скользящего окна. Скользящее окно можно представить в виде динамической структуры данных который организован так, чтобы запоминать «сказанную» ранее информацию и предоставлять к ней доступ. Таким образом, сам процесс сжимающего кодирования согласно LZ77 напоминает написание программы, команды которой позволяют обращаться к элементам «скользящего окна», и вместо значений сжимаемой последовательности вставлять ссылки на эти значения в «скользящем окне». В стандартном алгоритме LZ77 совпадения строки кодируются парой:

  • длина совпадения (match length)
  • смещение (offset) или дистанция (distance)

Кодируемая пара трактуется именно как команда копирования символов из скользящего окна с определенной позиции, или дословно как: «Вернуться в словаре на значение смещения символов и скопировать значение длины символов, начиная с текущей позиции». Особенность данного алгоритма сжатия заключается в том, что использование кодируемой пары длина-смещение является не только приемлемым, но и эффективным в тех случаях, когда значение длины превышает значение смещения. Пример с командой копирования не совсем очевиден: «Вернуться на 1 символ назад в буфере и скопировать 7 символов, начиная с текущей позиции». Каким образом можно скопировать 7 символов из буфера, когда в настоящий момент в буфере находится только 1 символ? Однако следующая интерпретация кодирующей пары может прояснить ситуацию: каждые 7 последующих символов совпадают (эквивалентны) с 1 символом перед ними. Это означает, что каждый символ можно однозначно определить, переместившись назад в буфере — даже если данный символ еще отсутствует в буфере на момент декодирования текущей пары длина-смещение.

Описания алгоритма

LZ77 использует "скользящее" по сообщению окно. Допустим на текущей итерации окно зафиксировано. С правой стороны окна наращиваем подстроку пока она есть в строке скользящее окно+наращиваемая строка и начинается в скользящем окне. Назовем наращиваемую строку буфером. После наращивания алгоритм выдает код состоящий из трех элементов:

  • смещение в окне;
  • длина буфера;
  • последний символ буфера.

В конце итерации алгоритм сдвигает окно на длину равную длине буфера+1.

Пример "kabababababz"

Содержимое окна(длина равна 4) Содержимое буфера КОД
'....'( 'k' <0,0,'k'>
'....'( 'a' <0,0,'a'>
'...a' 'b' <0,0,'b'>
'..ab' 'aba' <2,2,a>
'baba' 'bababz' <2,5,'z'>

LZ78

В отличие от LZ77, работающего с уже полученными данными, LZ78 ориентируется на данные, которые только будут получены (LZ78 не использует «скользящее» окно, он хранит словарь из уже просмотренных фраз). Алгоритм считывает символы сообщения до тех пор, пока накапливаемая подстрока входит целиком в одну из фраз словаря. Как только эта строка перестанет соответствовать хотя бы одной фразе словаря, алгоритм генерирует код, состоящий из индекса строки в словаре, которая до последнего введенного символа содержала входную строку, и символа, нарушившего совпадение. Затем в словарь добавляется введенная подстрока. Если словарь уже заполнен, то из него предварительно удаляют менее всех используемую в сравнениях фразу.

Ссылки