LZ77算法的基本原理

 

讓我們熟悉一下 LZ77 算法的基本流程。

1、從當前壓縮位置開始,考察未編碼的數據,並試圖在滑動窗口中找出最長的匹配字符串,如果找到,則進行步驟 2,否則進行步驟 3。

2、輸出三元符號組 ( off, len, c )。其中 off 爲窗口中匹配字符串相對窗口邊界的偏移,len 爲可匹配的長度,c 爲下一個字符。然後將窗口向後滑動 len + 1 個字符,繼續步驟 1。

3、輸出三元符號組 ( 0, 0, c )。其中 c 爲下一個字符。然後將窗口向後滑動 len + 1 個字符,繼續步驟 1。

我們結合實例來說明。假設窗口的大小爲 10 個字符,我們剛編碼過的 10 個字符是:abcdbbccaa,即將編碼的字符爲:abaeaaabaee

我們首先發現,可以和要編碼字符匹配的最長串爲 ab ( off = 0, len = 2 ), ab 的下一個字符爲 a,我們輸出三元組:( 0, 2, a )

現在窗口向後滑動 3 個字符,窗口中的內容爲:dbbccaaaba

下一個字符 e 在窗口中沒有匹配,我們輸出三元組:( 0, 0, e )

窗口向後滑動 1 個字符,其中內容變爲:bbccaaabae

我們馬上發現,要編碼的 aaabae 在窗口中存在( off = 4, len = 6 ),其後的字符爲 e,我們可以輸出:( 4, 6, e )

這樣,我們將可以匹配的字符串都變成了指向窗口內的指針,並由此完成了對上述數據的壓縮。

解壓縮的過程十分簡單,只要我們向壓縮時那樣維護好滑動的窗口,隨着三元組的不斷輸入,我們在窗口中找到相應的匹配串,綴上後繼字符 c 輸出(如果 off 和 len 都爲 0 則只輸出後繼字符 c )即可還原出原始數據。

當然,真正實現 LZ77 算法時還有許多複雜的問題需要解決,下面我們就來對可能碰到的問題逐一加以探討。

編碼方法

我們必須精心設計三元組中每個分量的表示方法,才能達到較好的壓縮效果。一般來講,編碼的設計要根據待編碼的數值的分佈情況而定。對於三元組的第一個分量——窗口內的偏移,通常的經驗是,偏移接近窗口尾部的情況要多於接近窗口頭部的情況,這是因爲字符串在與其接近的位置較容易找到匹配串,但對於普通的窗口大小(例如 4096 字節)來說,偏移值基本還是均勻分佈的,我們完全可以用固定的位數來表示它。

編碼 off 需要的位數 bitnum = upper_bound( log2( MAX_WND_SIZE ))

由此,如果窗口大小爲 4096,用 12 位就可以對偏移編碼。如果窗口大小爲 2048,用 11位就可以了。複雜一點的程序考慮到在壓縮開始時,窗口大小並沒有達到MAX_WND_SIZE,而是隨着壓縮的進行增長,因此可以根據窗口的當前大小動態計算所需要的位數,這樣可以略微節省一點空間。

對於第二個分量——字符串長度,我們必須考慮到,它在大多數時候不會太大,少數情況下才會發生大字符串的匹配。顯然可以使用一種變長的編碼方式來表示該長度值。在前面我們已經知道,要輸出變長的編碼,該編碼必須滿足前綴編碼的條件。其實 Huffman編碼也可以在此處使用,但卻不是最好的選擇。適用於此處的好的編碼方案很多,我在這裏介紹其中兩種應用非常廣泛的編碼。

第一種叫 Golomb 編碼。假設對正整數 x 進行 Golomb 編碼,選擇參數 m,令

b = 2m

q = INT((x - 1)/b)

r = x - qb - 1

則 x 可以被編碼爲兩部分,第一部分是由 q 個 1 加 1 個 0 組成,第二部分爲 m 位二進制數,其值爲 r。我們將 m = 0, 1, 2, 3 時的 Golomb 編碼表列出:

   值 x        m = 0       m = 1       m = 2       m = 3
-------------------------------------------------------------
    1             0         0 0        0 00        0 000
    2            10         0 1        0 01        0 001
    3           110        10 0        0 10        0 010
    4          1110        10 1        0 11        0 011
    5         11110       110 0       10 00        0 100
    6        111110       110 1       10 01        0 101
    7       1111110      1110 0       10 10     

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章