日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

理解 zip 和 gzip 壓縮格式背后的壓縮算法

 

眾所周知,通過網(wǎng)絡(luò)上傳或者下載數(shù)據(jù)的每一個字節(jié)都是要花流量的,即需要花錢的。盡管現(xiàn)存的壓縮算法已經(jīng)有幾十上百種,但其中最流行的壓縮算法可能還是 zip。gzip 壓縮算法雖然和 zip 有著相似的名字,但卻是另一種不同的算法。gzip 算法應(yīng)用也相當廣泛,它被 HTTP 三種標準壓縮規(guī)范之一(譯者注:屬于端到端壓縮技術(shù),參見 HTTP 協(xié)議中的數(shù)據(jù)壓縮 )所采用。雖然各種壓縮算法適用于不同場景,但是它們的底層都是基于 DEFLATE 。 DEFLATE是同時使用了 LZ77 算法與 哈夫曼編碼 (Huffman Coding)的一種無損數(shù)據(jù)壓縮算法。

LZ77

DEFLATE基于 LZ77 算法——這是一種用于文本壓縮的無損壓縮技術(shù)。

壓縮

LZ77算法通過使用編碼器或者解碼器中已經(jīng)出現(xiàn)過的相應(yīng)匹配數(shù)據(jù)信息替換當前數(shù)據(jù)從而實現(xiàn)壓縮功能。

此算法并非同時在整個文本中查找重復(fù)的字母,一般會先設(shè)定一個固定大小的搜索緩沖區(qū),例如 20(在真實場景中,這個緩沖區(qū)的大小一般是幾十 kB )。接著在逐一對文本中字母進行編碼時,首先會判斷當前字母是否有出現(xiàn)在前面緩沖區(qū)的 20 個字母中。如果能找到匹配的字母,就記錄下當前字母與找到的字母的偏移量 d ,這樣就完成了一個字母編碼的第一階段。接來下,用當前在編碼字母鄰近的下一個字母與緩沖區(qū)中匹配上字母鄰近的下一字母進行匹配,如果匹配上就繼續(xù)進行下一個字母的匹配,如此循環(huán)往復(fù)直到緩沖區(qū) 20 個字母匹配完或者鄰近的字母未匹配上,就結(jié)束匹配過程。結(jié)束上述過程后,將當前位置匹配上的連續(xù)字母替換成與緩沖區(qū)字母的偏移量以及這段連續(xù)字母的個數(shù) l 。這樣,字母編碼的第二階段就完成了。

讓我們用這個例子來看看它是如何工作的:

ERTOORTORR

首先能想到的最簡單做法就是直接替換第二次出現(xiàn)的 O 為指向第一次出現(xiàn)的 O 的一個標記,或者替換第二次出現(xiàn)的 RTO 為指向第一次出現(xiàn)的 RTO 。

下面更具體地描述一下這個過程,假定我們設(shè)置的緩沖區(qū)大小是 4,把這 4 個長度的緩沖區(qū)看成是一個滑動窗口沿著正文文本向右滑動:

1) [....E]RTOORTORR
2) [...ER]TOORTORR
3) [..ERT]OORTORR
4) [.ERTO]ORTORR
5) [ERTOO]RTORR -> ERTO(1, 1)RTOORR
6) E[RTOOR]TORR -> ERTO(1, 1)(4, 3)RR
7) ERTO[ORTOR]R -> ERTO(1, 1)(4, 3)(3, 1)R
8) ERTOO[RTORR] -> ERTO(1, 1)(4, 3)(3, 1)(1, 1)

滑動窗口隨著隨著編碼的迭代一步步向右移動,前面 4 步中滑動窗口內(nèi)的字母都沒有發(fā)現(xiàn)重復(fù)。到了第 5 步,滑動窗口內(nèi)字母 O 已經(jīng)出現(xiàn)重復(fù)了,然后查看字母 O 右側(cè)的 R 發(fā)現(xiàn)在滑動窗口中匹配字母 O 右側(cè)相鄰的字母并非 R ,便不再繼續(xù)向右進行匹配,將第 2 個 O 替換成 (1, 1) (表示:滑動窗口中匹配的字母離當前字母偏移距離為 1,匹配上的連續(xù)字母長度為 1)。在第 6 步中,滑動窗口中字母 R 與其左邊第 4 個字母匹配上了,繼續(xù)檢查下一個字母 T 的匹配情況,然后發(fā)現(xiàn)滑動窗口中 RT 也匹配上了。然后繼續(xù)下一個字母 O ,在滑動窗口中匹配 RTO 也匹配上了,并且到此為止,因為下一個字母匹配上了。滑動窗口中匹配上的字母與當前字母的偏移距離為 4,同時有連續(xù) 3 個字母匹配上了,所以這里將匹配上的 3 個字母替換成 (4, 3) 。接著在第 7 步中,字母 R 與偏移距離 3 出的字母匹配上,但是接下來的 RR 并未匹配上,在第 8 步中發(fā)現(xiàn)最近的匹配上的 R 的偏移距離為 1。最終整段文本經(jīng)過編碼的結(jié)果如下:

ERTO(1, 1)(4, 3)(3, 1)(1, 1)

解壓

壓縮過的文本其實是由一系列的這種 (d, 1) 標記對和字母組成,標記對無法直接找到相匹配的字母。在解壓過程中,字母保持不變,這種標記對轉(zhuǎn)換為其指向位置的字母。下面看一個解壓的例子:

abc(3, 2)(1, 1)

字母 abc 保持不變,標記對 (3, 2) 表示從當前位置向左移動 3 個單位,然后取出 2 個字母,因此其轉(zhuǎn)換為 ab 。現(xiàn)在原始文本變成了這樣 abcab(1, 1) ,最后的一個標記對表示從當前位置向左移動 1 個單位,然后取出 1 個字母,因此轉(zhuǎn)換為 b 。最終解壓完成的文本為 abcabb 。

哈夫曼編碼

在用 LZ77 消除了文本中重復(fù)的字母后,再使用 哈夫曼編碼 進行第二次壓縮。這種方法用較短的編碼代替較常用的字母,用較長的編碼代替較少用的字母,從而減少了文本的總長度。

讓我們用一個簡單的示例文本來看看它是如何工作的。

壓縮

EFTUPOEERRREOOPRRUTUTTEEE

這個例子中,我們希望能無損地壓縮這段文本。通常一個字母占用 8 字節(jié),所以這段文本總長度有 200 字節(jié)。在這段本文中,我們發(fā)現(xiàn)其中字母 F 只出現(xiàn)了 1 次,而字母 E 出現(xiàn)了 7 次。哈夫曼編碼正是利用了這一特性,通過減少出現(xiàn)頻率高的字母本身的字節(jié)長度,來減少整個文本所占的總長度。

要采用哈夫曼編碼壓縮文章,首先需要統(tǒng)計各個文本中各個字母的出現(xiàn)頻率,上述例子中的字母頻率如下:

頻率: 
E: 7, R: 5, T: 4, U: 3, O: 3, P: 2, F: 1

我們需要使用文本中的字母作為葉子節(jié)點來構(gòu)建一顆二叉樹,通過這顆二叉樹來編碼文本中的每一個字母。從出現(xiàn)頻率最小的字母: P 和 F 開始,讓其作為底層的葉子節(jié)點,將其頻率相加的值作為父節(jié)點,這樣便得到了如下的二叉樹:

(3)
                               /   
                             P(2)  F(1)

重復(fù)上面的步驟,依次使用頻率最小的字母: U 和 O 以及 R 和 T ,最后剩下頻率最高的字母 E 先單獨放著。

(6)                      (9)                      E(7)
      /                       /   
    U(3)  O(3)               R(5)  T(4)

接下來使用上面得到的 4 個二叉樹作為子節(jié)點來創(chuàng)建一顆更大的二叉樹,將上面的二叉樹的根節(jié)點的頻率值遞增排序,優(yōu)先使用根節(jié)點頻率值小的二叉樹作為新的二叉樹子節(jié)點。這里使用 U 和 O 、 R 和 T 這兩組二叉樹組成了如下的一顆二叉樹:

(9)
                               /   
                              /     
                            (6)     (3)
                           /      /   
                          U     O P     F

這時候還有 3 顆二叉樹,根節(jié)點分別為:9、9、7(第一個 9 是上一步創(chuàng)建的二叉樹),同樣的,將根節(jié)點頻率值最小的兩個作為子節(jié)點創(chuàng)建新的二叉樹如下:

(16)
                              /    
                             (9)    E
                            /   
                           /     
                         (6)     (3)
                        /      /   
U     O P     F
復(fù)制代碼

現(xiàn)在剩下一顆將根節(jié)點值為 16 的大二叉樹和根節(jié)點值為 9 葉子節(jié)點為 R 、 T 的二叉樹,將其作為子節(jié)點創(chuàng)建一顆新的二叉樹如下:

(25)
                                  /    
                                 /      
                               (16)     (9)
                              /       /   
                             (9)    E R     T
                            /   
                           /     
                         (6)     (3)
                        /      /   
                       U     O P     F

現(xiàn)在我們要做的就是根據(jù)這棵二叉樹來對文本進行編碼。依次從跟節(jié)點訪問各個字母,遇到左分支當成 0,遇到右分支當成 1,按照字母沿著二叉樹訪問路徑的順序所將這些 0、1 連接起來。比如,從根節(jié)點到字母 E 先后需要經(jīng)過 1 次左分支和 1 次右分支,所以字母 E 的編碼為 10 。字母 U 需要經(jīng)過 4 次左分支,其編碼為 1111 ; F 需要經(jīng)過 2 次左分支和 2 次右分支,其編碼為 1100 。可以發(fā)現(xiàn),在這里例子中出現(xiàn)頻率非常高的字母 E 編碼后位數(shù)比出現(xiàn)頻率較少的字母 F 編碼后位數(shù)要少。經(jīng)過這樣的編碼處理,最終壓縮過的文本如下:

10110000111111011110101001010110111011101101010111110011110000101010

這段壓縮后的文本長度只有 68 位,遠比原始的 200 位長度小。

解壓

假如收到這樣一段壓縮過的文本,我們希望能夠解壓它讓其變得可以理解。我們都知道一段未壓縮過的文本中的一個字符占用 8 位,上面說過經(jīng)過哈夫曼編碼壓縮后一個字符的位數(shù)并不是固定 8 位的,所以并不清楚一段數(shù)據(jù)(比如: 011 )是表示 1 個字符、2 個字符或者 3 個字符,因此這段壓縮過的文本將如何解壓呢?

這一步不存在任何奇跡,要準確解壓還需要上面編碼中構(gòu)建的二叉樹。得到這個用于編碼的二叉樹有兩種方案,第一種是其和壓縮后的文本放一起作為原始文本的壓縮結(jié)果,這可能會導(dǎo)致壓縮后的文本比原始文本還要大;第二種方案是使用預(yù)先定義好的二叉樹。我們知道各個字母在英語中的使用頻率,完全可以根據(jù)這個頻率來構(gòu)建上述的二叉樹。使用這種預(yù)先定義的公共字母頻率二叉樹壓縮部分文本的結(jié)果可能比根據(jù)文本內(nèi)容字母頻率二叉樹壓縮的效果差一些,但是這樣不再需要將字母頻率二叉樹保存到壓縮后的文件中。總而言之,這兩種方案各有優(yōu)缺點。

雖然本文沒有深入的分析各種壓縮算法原理的細節(jié)和對應(yīng)的實現(xiàn),但是經(jīng)過上述講解你應(yīng)該已經(jīng)對文本如何被壓縮成 zip 和 gzip 等格式有了大概的認識。希望本文能滿足你對壓縮算法神秘面紗的好奇心:)

* 從技術(shù)上來說,zip 壓縮格式是支持使用其他的壓縮算法的,但是 DEFLATE 是其中最常用的一種。

分享到:
標簽:算法 壓縮
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運動步數(shù)有氧達人2018-06-03

記錄運動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定