1. 程式人生 > >無損資料壓縮演算法的歷史

無損資料壓縮演算法的歷史

引言

有兩種主要的壓縮演算法: 有損和無損。有失真壓縮演算法通過移除在保真情形下需要大量的資料去儲存的小細節,從而使檔案變小。在有失真壓縮裡,因某些必要資料的移除,恢復原檔案是不可能的。有失真壓縮主要用來儲存影象和音訊檔案,同時通過移除資料可以達到一個比較高的壓縮率,不過本文不討論有失真壓縮。無失真壓縮,也使檔案變小,但對應的解壓縮功能可以精確的恢復原檔案,不丟失任何資料。無損資料壓縮被廣泛的應用於計算機領域,從節省你個人電腦的空間,到通過web傳送資料。使用Secure Shell交流,檢視PNG或GIF圖片。

無失真壓縮演算法可行的基本原理是,任意一個非隨機檔案都含有重複資料,這些重複資料可以通過用來確定字元或短語出現概率的統計建模技術來壓縮。統計模型可以用來為特定的字元或者短語生成程式碼,基於它們出現的頻率,配置最短的程式碼給最常用的資料。這些技術包括熵編碼(entropy encoding),遊程編碼(run-length encoding),以及字典壓縮。運用這些技術以及其它技術,一個8-bit長度的字元或者字串可以用很少的bit來表示,從而大量的重複資料被移除。

歷史

 

 

直到20世紀70年代,資料壓縮才在計算機領域開始扮演重要角色,那時網際網路變得更加流行,Lempel-Ziv演算法被髮明出來,但壓縮演算法在計算機領域之外有著更悠久的歷史。發明於1838年的Morse code,是最早的資料壓縮例項,為英語中最常用的字母比如"e"和"t"分配更短的Morse code。之後,隨著大型機的興起,Claude Shannon和Robert Fano發明了Shannon-Fano編碼演算法。他們的演算法基於符號(symbol)出現的概率來給符號分配編碼(code)。一個符號出現的概率大小與對應的編碼成反比,從而用更短的方式來表示符號。

兩年後,David Huffman在MIT學習資訊理論並上了一門Robert Fano老師的課,Fano給班級的同學兩個選項,寫一篇學期論文或者參加期末考試。Huffman選擇的是寫學期論文,題目是尋找二叉編碼的最優演算法。經過幾個月的努力後依然沒有任何成果,Huffman決定放棄所有論文相關的工作,開始學習為參加期末考試做準備。正在那時,靈感爆發,Huffman找到一個與Shannon-Fano編碼相類似但是更有效的編碼演算法。Shannon-Fano編碼和Huffman編碼的主要區別是構建概率樹的過程不同,前者是自下而上,得到一個次優結果,而後者是自上而下。

早期的Shannon-Fano編碼和Huffman編碼演算法實現是使用硬體和硬編碼完成的。直到20世紀70年代網際網路以及線上儲存的出現,軟體壓縮才被實現為Huffman編碼依據輸入資料動態產生。隨後,1977年Abraham Lempel 和 Jacob Ziv發表了他們獨創性的LZ77演算法,第一個使用字典來壓縮資料的演算法。特別的,LZ77使用了一個叫做slidingwindow的動態字典。1778年,這對搭檔發表了同樣使用字典的LZ78演算法。與LZ77不同,LZ78解析輸入資料,生成一個靜態字典,不像LZ77動態產生。

法律問題

LZ77和LZ78都快速的流行開來,衍生出多個下圖中所示的壓縮演算法。其中的大多數已經沉寂了,只有那麼幾個現在被大範圍的使用,包括DEFLATE,LZMA以及LZX。絕大多數常用的壓縮演算法都衍生於LZ77,這不是因為LZ77技術更好,只是由於Sperry在1984年申請了LZ78衍生演算法LZW的專利,從而發展受到了專利的阻礙,Sperry開始因專利侵權而起訴軟體提供商,伺服器管理員,甚至是使用GIF格式但沒有License的終端使用者。

同時,UNIX壓縮工具使用了一個叫LZC的LZW演算法微調整版本,之後由於專利問題而被棄用。其他的UNIX開發者也開始放棄使用LZW。這導致UNIX社群採用基於DEFLATE的gzip和基於Burrows-Wheeler Transform的bzip2演算法。長遠來說,對於UNIX社群這是有好處的,因為gzip和bzip2格式幾乎總是比LZW有更好的壓縮比。圍繞LZW的專利問題已經結束,因為LZW的專利2003年就到期了。儘管這樣,LZW演算法已經很大程度上被替代掉了,僅僅被使用於GIF壓縮中。自那以後,也有一些LZW的衍生演算法,不過都沒有流行開來,LZ77演算法仍然是主流。

另外一場法律官司發生於1993,關於LZS演算法。LZS是由Stac Electronics開發的,用於硬碟壓縮軟體,如Stacker。微軟在開發影片壓縮軟體時使用了LZS演算法,開發的軟體隨著MS-DOS 6.0一起釋出,聲稱能夠使硬碟容量翻倍。當Stac Electronics發現自己的知識財產被使用後,起訴了微軟。微軟隨後被判專利侵權並賠償Stac Electronics1億2000萬美元,後因微軟上訴因非故意侵權而減少了1360萬美元。儘管Stac Electronics和微軟發生了一個那麼大的官司,但它沒有阻礙Lempel-Ziv演算法的開發,不像LZW專利糾紛那樣。唯一的結果就是LZS沒有衍生出任何演算法。

Deflate的崛起

自從Lempel-Ziv演算法被髮表以來,隨著對儲存需求的不斷增長,一些公司及其他團體開始使用資料壓縮技術,這能讓他們滿足這些需求。然而,資料壓縮並沒有被大範圍的使用,這一局面直到20世紀80年代末期隨著網際網路的騰飛才開始改變,那時資料壓縮的需求出現了。頻寬限額,昂貴,資料壓縮能夠幫助緩解這些瓶頸。當全球資訊網發展起來之後人們開始分享更多的圖片以及其它格式的資料,這些資料遠比文字大得多,壓縮開始變得極其重要。為了滿足這些需求,幾個新的檔案格式被開發出來,包括ZIP,GIF,和PNG。

Thom Henderson通過他的公司釋出了第一個成功的商業存檔格式,叫做ARC,公司名為為System Enhancement Associates。ARC在BBS社群尤為流行,這是因為它是第一個既可以打包又可以壓縮的程式,此外還開放了原始碼。ARC格式使用一個LZW的衍生演算法來壓縮資料。一個叫做Phil Katz的家注意到了ARC的流行並決定用匯編語言來重寫壓縮和解壓縮程式,希望改進ARC。他於1987釋出了他的共享軟體PKARC程式,不久被Henderson以侵犯版權為由起訴。Katz被認定為有罪,並被迫支付版權費用以及其它許可協議費用。他之所以被認定侵權,是由於PKARC是明顯抄襲ARC,甚至於一些註釋裡面的錯別字都相同。

Phil Katz自1988年之後就因許可證問題不能繼續出售PKARC,所以1989年他建立了一個PKARC的修改版,就是現在大家熟知的ZIP格式。由於使用了LZW,它被認為專利侵權的,之後Katz選擇轉而使用新的IMPLODE演算法,這種格式於1993年再次被修改,那時Kata釋出了PKZIP的2.0版本,那個版本實現了DEFLATE演算法以及一些其它特性,如分割容量等。這個ZIP版本也是我們現在隨處可見的格式,所有的ZIP檔案都遵循PKZIP 2.0格式,儘管它年代久遠。

GIF格式,全稱Graphics Interchange Format,於1987年由CompuServe建立,允許影象無失真地被共享(儘管這種格式被限定每一幀最多256種顏色),同時減小檔案的大小以允許通過資料機傳輸。然而,像ZIP格式一樣,GIF也是基於LZW演算法。儘管專利侵權,Unisys沒有辦法去阻止GIF的傳播。即使是現在,20年後的今天,GIF仍然被使用著,特別是它的動畫能力。

儘管GIF沒有辦法被叫停,CompuServe需找一種不受專利束縛的格式,並於1994年引入了Portable Network Graphics (PNG) 格式。像ZIP一樣,PNG使用DEFLATE演算法來處理壓縮。儘管DELLATE的專利屬於Katz,這個專利並不是強性制的,正是這樣,PNG以及其它基於DEFLATE的格式避免了專利侵權。儘管LZW在壓縮歷史的初期佔據霸主位置,由於Unisys公司的好訴訟作為,LZW慢慢的淡出主流,大家轉而使用更快更高效的DEFLATE演算法。現在DEFLATE是使用得最多的演算法,有些壓縮世界裡瑞士軍刀的味道。

除了用於PNG和ZIP格式之外,計算機世界裡DEFLATE也被頻繁的用在其它地方。例如gzip(.gz)檔案格式也使用了DEFLATE,gzip是ZIP的一個開源版本。其它還包括HTTP, SSL, 以及其它的高效壓縮網路傳輸資料的技術。

遺憾的是,Phil Katz英年早逝,沒能看到他的DEFLATE演算法統治計算機世界。有幾年的時間他酗酒成性,生活也於20世紀90年代末期開始支離破碎,好幾次因酒駕或者其它違法行為而被逮捕。Katz於2000年4月14號被發現死於一個酒店的房間,終年37歲。死因是酒精導致的嚴重胰腺出血,身旁是一堆的空酒瓶。

當前的一些歸檔軟體

ZIP以及其它基於DEFLATE的格式一直佔據主導地位,直到20世紀90年代中期,一些新的改進的格式開始出現。1993年,Eugene Roshal釋出了一個叫做WinRAR的歸檔軟體,該軟體使用RAR格式。最新的RAR結合了PPM和LZSS演算法,前面的版本就不太清楚了。RAR開始在網際網路分享檔案方面成為事實標準,特別是盜版影像的傳播。1996年一個叫bzip2d的Burrows-Wheeler Transform演算法開源實現釋出,並很快在UNIX平臺上面流行開來,大有對抗基於DEFLATE演算法的gzip格式。1999年另外一個開源壓縮程式釋出了,以7-Zip或.7z的格式存在,7-Zip應該是第一個能夠挑戰ZIP和RAR霸主地位的格式,這源於它的高壓縮比,模組化以及開放性。這種格式並不僅限於使用一種壓縮演算法,而是可以在bzip2, LZMA, LZMA2, 和 PPMd演算法之間任意選擇。最後,歸檔軟體中較新的一個格式是PAQ*格式。第一個PAQ版本於2002年由Matt Mahoney釋出,叫做PAQ1。PAQ主要使用一種叫做context mixing的技術來改進PPM演算法,context mixing結合了兩個甚至是多個統計模型來產生一個更好的符號概率預測,這要比其中的任意一個模型都要好。

壓縮技術

有許多不同的技術被用來壓縮資料。大多數技術都不能單獨使用,需要結合起來形成一套演算法。那些能夠單獨使用的技術比需要結合的技術通常更加有效。其中的絕大部分都歸於entropy編碼類別下面,但其它的一些技術也挺常用,如Run-Length Encoding和Burrows-Wheeler Transform。

Run-Length Encoding

Run-Length Encoding是一個非常簡單的壓縮技術,把重複出現的多個字元替換為重複次數外加字元。單個字元次數為1。RLE非常適合資料重複度比較高的資料,同一行有很多畫素顏色相同的漸進圖片,也可以結合Burrows-Wheeler Transform等其它技術一起使用。

下面是RLE的一個簡單例子:

輸入: AAABBCCCCDEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA輸出: 3A2B4C1D6E38A

Burrows-Wheeler Transform

Burrows-Wheeler Transform是1994年發明的技術,目的是可逆的處理一段輸入資料,使得相同字元連續出現的次數最大化。BWT自身並不做任何的壓縮操作,僅簡單地轉化資料,讓Run-Length Encoder等壓縮演算法可以更有效的編碼。

BWT演算法很簡單:

  1. 建立一個字串陣列。
  2. 把輸入字串的所有排列組合塞入上述字串陣列。
  3. 按照字元順序為字串陣列排序。
  4. 返回陣列的最後一列。

BWT通常處理有很多交叉重複字元的長字串時效果很好。下面是一個有著理想輸入的例子,注意&是檔案結束符:

因為交換相同的符號到一起,輸入資料在BWT處理之後得到優化後的結果,另外一個演算法可以對該結果進行壓縮,比如RLE會得到"3H&3A"。儘管這個例子得到了一個較優的結果,不過現實世界中的資料它不總是這樣。

Entropy Encoding

資料壓縮中,平均來說為了表示一個字元或短語,Entropy意味著所需要的最少bit數。一個基本的entropy編碼器包括一個分析模型以及一套編碼。輸入檔案被解析,併產生一個由字元出現概率組成的統計模型。然後,編碼器可以利用該統計模型去決定該給每一個字元多少個bit,從而使得最常用的字元用最短的編碼,反之最不常用的字元用最長的編碼。

Shannon-Fano Coding

這是最早的壓縮技術,於1949年由Claude Shannon和Robert Fano發明。這個技術的其中一個步驟是產生一個代表字元出現概率的二叉樹。字元以這樣一種方式排序,出現得越頻繁的字元越靠近樹的頂端,越不常見的越靠近樹的底部。

一個字元對應的編碼通過搜尋Shannon-Fano來獲得,此外,左分支後面加0,右分支加1。例如,"A"是兩個左節點後接一個右節點,那麼對於的編碼為"0012"。Shannon-Fano coding不總是能夠產生最優的編碼,主要是由於二叉樹是自下而上構建的。由於這個原因,使用的較多的還是對於任意輸入都能夠得到最優編碼的Huffman coding。

產生Shannon-Fano編碼的演算法很簡單:

  1. 解析輸入,統計每一個字元出現的頻率。
  2. 根據是上述頻率計算字元的概率。
  3. 依據概率對字元降序排序。
  4. 為每一個字元生成一個葉節點(LeafNode)
  5. 把字元列表分為左右兩部分,使得左邊的概率與右邊的概率大致相當。
  6. 左節點加編碼"0",右節點加編碼"1"。
  7. 對兩棵子樹重複的步驟5和6,直到所有的字元節點都成為葉子節點。

Huffman Coding

Huffman Coding是另外一個entropy coding的例子,與Shannon-Fano Coding非常的相似,只是為了產生最優編碼二叉樹是自上而下構建的。

生成Huffman編碼的演算法前面的三個步驟與Shannon-Fano完全相同:

  1. 解析輸入,統計每一個字元出現的頻率。
  2. 根據是上述頻率計算字元的概率。
  3. 依據概率對字元降序排序。
  4. 為每一個字元生成一個葉節點(LeafNode),節點包含概率資訊P,把節點存入一個佇列Queue。
  5. While (Nodes in Queue > 1)
    • 從佇列裡面取出概率最小的兩個節點。
    • 給左節點分配編碼"0",右節點分配編碼"1"。
    • 建立一個新的節點,其概率為上面步驟中的兩個節點之和。
    • 把兩個節點中的第一個設定為新建節點的左節點,第二個節點為新建節點的右節點。
    • 把新建節點存入佇列
  6. 最後一個節點就是二叉樹的根節點。

Arithmetic Coding

1979年該演算法在IBM被開發出來,當時IBM正在調研一些壓縮演算法,以期用於它們的大型機上。如果單論壓縮比,Arithmetic coding確實是一個最優的entropy coding技術,通常壓縮比方面Arithmetic Coding要比Huffman Coding表現得更好。然而,它卻也比其它技術複雜得多。

不像其它技術會把字元概率構建成一棵樹,arithmetic coding把輸入轉化為一個0到1之間的有理數,輸入字元的個數記為base,裡面每一個不同的字元都分配一個0到base之間的值。然後,最後轉化為二進位制得到最終的結果。結果也可以通過把base恢復為原來的base值,替換為對應字元而得到原輸入值。

一個基本的計算arithmetic code演算法如下:

  1. 計算輸入資料裡面不同字元的個數。這個數字記為base b(比如 base 2代表2二進位制)。
  2. 按字元出現的順序分別給每一個字元分配一個0到b之間的值。
  3. 使用步驟2中德值,把輸入中的字元替換為對應的數字(編碼)。
  4. 把步驟3中得到的結果從b進位制轉化為2進位制。
  5. 如果解碼需要的話,記錄輸入的字元總個數。

下面是一個編碼操作的例子,輸入為"ABCDAABD":

  1. 找到共有4個不同的字元輸入, base = 4, length = 8。
  2. 按出現順序為不同的字元賦值: A=0, B=1, C=2, D=3。
  3. 用編碼替換字元,得到“0.012300134”,注意最前面的"0."是為了得到小數而加上去的。最後的4表示base=4。
  4. 把“0.012300134”從4進位制轉化為2進位制,得到“0.011011000001112”。最後的2表示base=2。
  5. 在結果中標識輸入的總字元數為8。

假設字元為8個bit表示,輸入共需要64個bit空間,然而對應的arithmetic coding只有15個bit,壓縮比為24%,效果顯著。這個例子展示了arithmetic coding是如何良好的壓縮固定字串的。

壓縮演算法

Sliding Window Algorithms

LZ77

LZ77發表於1977年,是名副其實的壓縮演算法開山之作。它首次引入'sliding window'的概念,相較幾個主要的壓縮演算法,壓縮比都有非常明顯的提高。LZ77維護了一個字典,用一個三元組來表示offset,run length和分割字元。offset表示從檔案起始位置到當前Phase的起始位置的距離,run length記錄當前Phase有多少個字元,分割符僅用於分割不同的Phase。Phase就是offset到offset+length之間的子串減掉分隔符。隨著檔案解析的進行,基於sliding window字典會動態的變化。例如,64MB的sliding window意味著四點將包含64M的輸入資料的資訊。

給定一個輸入為"abbadabba",那麼輸出可能像"abb(0,1,'d')(0,3,'a')",如下圖所示:

儘管上述的替換看起來比原資料還要大,當輸入資料更大一些的時候,效果會比較好。

LZR

LZR是LZ77的修改版本,於1981年由Michael Rodeh發明。這個演算法目標是成為LZ77的一個線性時間替換演算法。然而,編碼後Udell指標可能指向檔案的任意offset,意味著需要耗費可觀的記憶體。加之壓縮比表現也差強人意(LZ77好得多),LZR算是一個不成功的LZ77衍生演算法。

DEFLATE

DEFLATE於1993年由Phil Katz發明,是現代絕大多數壓縮任務的基石。它僅僅結合了兩種演算法,先用LZ77或LZSS預處理,然後用Huffman編碼,快速的得到不錯的壓縮結果。

DEFLATE64

DEFLATE64是DEFLATE的一個有專利的擴充套件,把字典的大小提高到64K(名字隨之),從而允許在sliding window裡面有更大的距離。相比於DEFLATE,DEFLATE64在效能和壓縮比方面都有提高。然而,由於DEFLATE64的專利保護以及相較DEFLATE並沒有特別明顯的提高,DEFLATE64很少被採用。相反一些開源演算法如LZMA被大量的使用。

LZSS

LZSS,全稱Lempel-Ziv-Storer-Szymanski,於1982年由James Storer發表。LZSS相較LZ77有所提高,它能檢測到一個替換是否真的減小了檔案大小。如果檔案大小沒有減小,不再替換輸入值。此外,輸入段被(offset, length)資料對替換,其中offset表示離輸入起始位置的bytes數量,length表示從該位置讀取了多少個字元。另外一個改進是去除了"next character"資訊,僅僅使用offset-length資料對。

下面是一個輸入為" these theses"簡單的例子,結果為" these(0,6)s",僅僅節省了一個Byte,不過輸入資料大的時候效果會好得多。

LZSS依然被用在許多使用廣泛的歸檔格式中,其中最知名的是RAR。LZSS有時也被用於網路資料壓縮。

LZH

LZH發明於1987年,全稱為"Lempel-Ziv Huffman"。它是LZSS的一個衍生演算法,利用Huffman coding壓縮指標,壓縮效果有微小的提高。然而使用Huffman coding帶來的提高實在是很有限,相較於使用Huffman coding帶來的效能損失,不足為取。

LZB

LZB同樣發明於1987年,同樣是LZSS的衍生演算法。如LZH一樣,LZB也致力於通過更加有效的編碼指標以達到更好的壓縮效果。它的做法是隨著sliding window變大,逐步的增大指標的數量。它的壓縮效果確實比LZSS和LZH要好,不過因為額外的編碼步驟,速度上比LZSS慢得多。

ROLZ

ROLZ全稱"Reduced Offset Lempel-Ziv",它的目標是提高LZ77的壓縮效果,通過限制offset的大小,從而減少為offset-length資料對編碼的資料量。這項LZ77的衍生技術於1991年首次出現在Ross Williams的LZRW4演算法裡面。其它的實現包括BALZ,QUAD,和 RZM。高度優化的ROLZ能夠達到接近LZMA的壓縮比,不過ROLZ不太流行。

LZP

LZP全稱"Lempel-Ziv + Prediction"。它是ROLZ演算法的一個特殊案例,offset減小到1。有幾個衍生的演算法使用不同的技術來實現或加快壓縮速度,或提高壓縮比的目標。LZW4實現了一個數字編碼器達到了最好的壓縮比,不過犧牲了部分速度。

LZRW1

Ron Williams於1991年發明了這個演算法,第一次引入了Reduced-Offset Lempel-Ziv compressiond的概念。LZRW1能夠達到很高的壓縮比,同時保持快速有效。Ron Williams也發明另外幾個基於LZRW1改進的衍生演算法,如LZRW1-A, 2, 3, 3-A, 和4。

LZJB

Jeff Bonwick於1998年發明了Lempel-Ziv Jeff Bonwick演算法,用於Solaris作業系統的Z檔案系統(ZFS)。它被認為是LZRW演算法的一個衍生演算法,特別是LZRW1,目標是改進壓縮速度。既然它是被用於作業系統,速度顯得尤為重要,不能因為壓縮演算法的原因而使得磁碟操作成為瓶頸。

LZS

Lempel-Ziv-Stac演算法於1994年由Stac Electronics發明,用於磁碟壓縮軟體。它是LZ77的一個修改版本,區分了輸出的文字元號與offset-length資料對,此外還移除了分隔符。功能上來說,LZS與LZSS演算法很相似。

LZX

LZX演算法於1995年由Jonathan Forbes和Tomi Poutanen發明,用於Amiga計算機。LZX中X沒有什麼特殊的意義。Forbes於1996年把該演算法出售給了微軟,並且受僱於微軟,那那兒該演算法被繼續優化並用於微軟的cabinet(.CAB)格式。這個演算法也被微軟用於壓縮Compressed HTML Help (CHM) 檔案,Windows Imaging Format (WIM) 檔案,和 Xbox Live Avatars。

LZO

LZO於1996年由Markus發明,該演算法的目標是快速的壓縮和解壓縮。它允許調整壓縮級別,並且在最高級別下仍僅需64KB額外的記憶體空間,同時解壓縮僅需要輸入和輸出的空間。LZO功能上非常類似LZSS,不過是為了速度,而非壓縮比做的優化。

LZMA

Lempel-Ziv Markov chain Algorithm演算法於1998年首次發表,是隨著7-Zip歸檔軟體一起釋出的。大多數情況下它比bzip2, DEFLATE以及其它演算法表現都要好。LZMA使用一系列技術來完成輸出。首先時一個LZ77的修改版本,它操作的是bitwise級別,而非傳統上的bytewise級別,用於解析資料。LZ77演算法解析後的輸出經過數字編碼。更多的技術可被使用,這依賴於具體的LZMA實現。相比其它LZ衍生演算法,LZMA在壓縮比方面提高明顯,這要歸功於操作bitewise,而非bytewise。

LZMA2

LZMA2是LZMA的一個增量改進版本,於2009年在7-Zip歸檔軟體的一個更新版本里面首次引入。LZMA2改進了多執行緒處理功能,同時優化對不可壓縮資料的處理,這也稍微提高了壓縮效果。

Statistical Lempel-Ziv

Statistical Lempel-Ziv是於2001年由Sam Kwong博士和Yu Fan Ho博士提出的一個概念。基本的原則是資料的統計分析結果可以與LZ77衍生演算法結合起來,進一步優化什麼樣的編碼將儲存在字典中。

Dictionary Algorithms

LZ78

LZ78於1978年由Lempel和Ziv發明,縮寫正是來源於此。不再使用sliding window來生成字典,輸入資料要麼被預處理之後用來生成字典,或者字典在檔案解析過程中逐漸形成。LZ78採用了後者。字典的大小通常被限定為幾兆的大小,或者所有編碼上限為幾個位元,比如8個。這是出於減少對記憶體要求的考量。演算法如何處理正是LZ78的各個衍生演算法的區別所在。

解析檔案的時候,LZ78把新碰到的字元或者字串加到字典中。針對每一個符號,形如(dictionary index, unknown symbol)的字典記錄會對應地生成。如果符號已經存在於字典中,那麼將從字典中搜索該符號的子字串以及其後的其它符號。最長子串的位置即為字典索引(Index)。字典索引對應的資料被設定為最後一個未知子串。如果當前字元是未知的,那麼字典索引設定為0,表示它是單字元對。這些資料對形成一個連結串列資料結構。

形如"abbadabbaabaad"的輸入,將會產生"(0,a)(0,b)(2,a)(0,d)(1,b)(3,a)(6,d)"這樣的輸出。你能從下面的例子裡面看到它是如何演化的:

LZW

LZW於1984年由Terry Welch發明,全稱為Lempel-Ziv-Welch。它是LZ78大家族中被用得最多的演算法,儘管被專利嚴重的阻礙了使用。LZW改進LZ78的方法與LZSS類似。它刪除輸出中冗餘的資料,使得輸出中不再包含指標。壓縮之前它就在字典裡面包含了每一個字元,也引入了一些技術改進壓縮效果,比如把每一個語句的最後一個字元編碼為下一個語句的第一個字元。LZW在影象轉換格式中較為常見,早期也曾用於ZIP格式裡面,也包括一些其他的專業應用。LZW非常的快,不過相較於一些新的演算法,壓縮效果就顯得比較平庸。一些演算法會更快,壓縮效果也更好。

LZC

LZC,全稱Lempel-Ziv Compress,是LZW演算法的一個微小修改版本,用於UNIX壓縮工具中。LZC與LZW兩者的區別在於,LZC會監控輸出的壓縮比。當壓縮比超過某一個臨界值的時候,字典被丟棄並重構。

LZT

Lempel-Ziv Tischer是LZC的修改版,當字典滿了,刪除最不常用的的語句,用新的記錄替換它。還有一些其它的小改進,不過現在LZC和LZT都不常用了。

LZMW

於1984年由Victor Miller和Mark Wegman發明,LZMW演算法非常類似於LZT,它也採用了替換最不常用語句的策略。然而,不是連線字典中相似的語句,而是連線LZMW最後被編碼的兩個語句並且儲存為一條記錄。因此,字典的容量能夠快速擴充套件並且LRUs被更頻繁的丟棄掉。LZMW壓縮效果比LZT更好,然而它也是另外一個這個時代很難看到其應用的演算法。

LZAP

LZAP於1988年由James Storer發明,是LZMW演算法的修改版本。AP代表"all prefixes",以其遍歷時在字典裡面儲存單個語句,字典儲存了語句的所有排列組合。例如,如果最後一個語句為"last",當前語句是"next",字典將儲存"lastn","lastne","lastnex",和 "lastnext"。

LZWL

LZWL是2006年發明的一個LZW修改版本,處理音節而非字元。LZWL是專為有很多常用音節的資料集而設計的,比如XML。這種演算法通常會搭配一個前置處理器,用來把輸入資料分解為音節。

LZJ

Matti Jakobsson於1985年發表了LZJ演算法,它是LZ78大家族中唯一一位衍生於LZW的演算法。LZJ的工作方式是,在字典中儲存每一個經過預處理輸入中的不同字串,併為它們編碼。當字典滿了,移除所有隻出現一次的記錄。

Non-dictionary Algorithms

PPM

通過抽樣來預測資料是一項統計建模技術,使用輸入中的一部分資料,來預測後續的符號將會是什麼,通過這種演算法來減少輸出資料的entropy。該演算法與字典演算法不一樣,PPM預測下一個符號將會是什麼,而不是找出下一個符號來編碼。PPM通常結合一個編碼器來一起使用,如arithmetic編碼或者適配的Huffman編碼。PPM或者它的衍生演算法被實現於許多歸檔格式中,包括7-Zip和RAR。

bzip2

bzip2是Burrows-Wheeler Transform演算法的一個開源實現。它的操作原理很簡單,不過卻在壓縮比和速度之間達到了一個平衡,表現良好,這讓它在UNIX環境上很流行。首先,使用了一個Run-Length編碼器,接下來,Burrows-Wheeler Transform演算法加入進來,然後,使用move-to-front transform以達到產生大量相同符號的目標,為接下來的另一個Run-Length 編碼器做準備。最後結果用Huffman編碼,將一個訊息頭與其打包。

PAQ

PAQ於2002年由Matt Mahoney發明,是老版PPM的一個改進版。改進的方法是使用一項叫做context mixing的革命性技術。Context mixing是指智慧地結合多個(PPM是單個模型)統計模型,來做出對下一個符號的更好預測,比其中的任何一個模型都要好。PAQ是最有前途的技術之一,它有很好的壓縮比,開發也很活躍。自它出現後算起,有超過20個衍生演算法被髮明出來,其中一些在壓縮比方面屢破記錄。PAQ的最大缺點是速度,這源於使用了多個統計模型來獲得更好的壓縮比。然而隨著硬體速度的不斷提升,它或許會是未來的標準。PAQ在應用方面進步緩慢,一個叫PAQ8O的衍生演算法可以在一個叫PeaZip的Windows程式裡面找到,PAQ8O支援64-bit,速度也有較大提升。其它的PAQ格式僅僅用於命令列程式。

 

文章連結