欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
gzip壓縮算法 - c/c - CSDN技術(shù)中心
如果你有時(shí)間的話(huà),我建議你先不要看下面的內容,自己嘗試通過(guò)讀gzip源碼,來(lái)了解它的壓縮解壓縮是如何實(shí)現的,這將會(huì )是一個(gè)非常有趣的智力游戲,千萬(wàn)不要錯過(guò)。當一個(gè)又一個(gè)的謎被解開(kāi)時(shí),那感覺(jué)就像唐伯虎同志所說(shuō)的,慷慨然諾杯酒中。(小唐的詩(shī),除了另一個(gè)倒霉蛋曹雪芹外,好像不太被人提。)

   1 gzip所使用壓縮算法的基本原理

   gzip 對于要壓縮的文件,首先使用lz77算法進(jìn)行壓縮,對得到的結果再使用huffman編碼的方法進(jìn)行壓縮。所以我們分別對lz77huffman編碼的原理進(jìn)行說(shuō)明。

   1.1 ... 1.2 ...

   2 gzip壓縮算法實(shí)現方法

   2.1 LZ77算法的gzip實(shí)現

  首先,gzip 從要壓縮的文件中讀入64KB的內容到一個(gè)叫window的緩沖區中。為了簡(jiǎn)單起見(jiàn),我們以32KB以下文件的壓縮為例做說(shuō)明。對于我們這里使用32KB以下文件,gzip將整個(gè)文件讀入到window緩沖區中。然后使用一個(gè)叫strstart的變量在window數組中,從0開(kāi)始一直向后移動(dòng)。strstart在每一個(gè)位置上,都在它之前的區域中,尋找和當前strstart開(kāi)始的串的頭3個(gè)字節匹配的串,并試圖從這些匹配串中找到最長(cháng)的匹配串。

  如果當前的strstart開(kāi)始的串,可以找到最少為3個(gè)字節的匹配串的話(huà),當前的strstart開(kāi)始的匹配長(cháng)度那么長(cháng)的串,將會(huì )被一個(gè)<匹配長(cháng)度,到匹配串開(kāi)頭的距離>對替換。

  如果當前的strstart開(kāi)始的串,找不到任何的最少為3個(gè)字節的匹配串的話(huà),那么當前strstart的所在字節將不作改動(dòng)。

  為了區分是一個(gè)<匹配長(cháng)度,到匹配串開(kāi)頭的距離>對,還是一個(gè)沒(méi)有被改動(dòng)的字節,還需要為每一個(gè)沒(méi)有被改動(dòng)的字節或者<匹配長(cháng)度,到匹配串開(kāi)頭的距離>對,另外再占用一
  位,來(lái)進(jìn)行區分。這位如果為1,表示是一個(gè)<匹配長(cháng)度,到匹配串開(kāi)頭的距離>對,這位如果為0,表示是一個(gè)沒(méi)有被改動(dòng)的字節。

  現在來(lái)說(shuō)明一下,為什么最小匹配為3個(gè)字節。這是由于,gzip 中,<匹配長(cháng)度,到匹配串開(kāi)頭的距離>對中,"匹配長(cháng)度"的范圍為3-258,也就是256種可能值,需要8bit來(lái)保存。"到匹配串開(kāi)頭的距離"的范圍為0-32K,需要15bit來(lái)保存。所以一個(gè)<匹配長(cháng)度,到匹配串開(kāi)頭的距離>對需要23位,差一位3個(gè)字節。如果匹配串小于3個(gè)字節的話(huà),使用<匹配長(cháng)度,到匹配串開(kāi)頭的距離>對進(jìn)行替換,不但沒(méi)有壓縮,反而還會(huì )增大。所以保存<匹配長(cháng)度,到匹配串開(kāi)頭的距離>對所需要的位數,決定了最小匹配長(cháng)度至少要為3個(gè)字節。

  下面我們就來(lái)介紹gzip如何實(shí)現尋找當前strstart開(kāi)始的串的最長(cháng)匹配串。

  如果每次為當前串尋找匹配串時(shí),都要和之前的每個(gè)串的至少3個(gè)字節進(jìn)行比較的話(huà),那么比較量將是非常非常大的。為了提高比較速度,gzip使用了哈希表。這是gzip實(shí)現LZ77的關(guān)鍵。這個(gè)哈希表是一個(gè)叫head的數組(后面我們將看到為什么這個(gè)緩沖區叫head)。gzipwindows中的每個(gè)串,使用串的頭三個(gè)字節,也就是strstart,strstart 1,strstart 2,用一個(gè)設計好的哈希函數來(lái)進(jìn)行計算,得到一個(gè)插入位置ins_h。也就是用串的頭三個(gè)字節來(lái)確定一個(gè)插入位置。然后把串的位置,也就是 strstart的值,保存在head數組的第ins_h項中。我們馬上就可以看到為什么要這樣做。head數組在沒(méi)有插入任何值時(shí),全部為0。
當某處的當前串的三個(gè)字節確定了一個(gè)ins_h,并把當時(shí)當前串的位置也就是當時(shí)的strstart保存在了head[ins_h]中。之后另一處,當另一處的當前串的頭三個(gè)字節,再為那三個(gè)字節時(shí),再使用那個(gè)哈希函數來(lái)計算,由于是同樣的三個(gè)字節,同樣的哈希函數,得到的ins_h必然和前面得到的ins_h是相同的。于是就會(huì )發(fā)現head[ins_h]不為0。這就說(shuō)明了,有一個(gè)頭三個(gè)字節和自己相同的串把自己的位置保存在了這里,現在head[ins_h]中保存的值,也就是那個(gè)串的開(kāi)始位置,我們就可以找到那個(gè)串,那個(gè)串至少前3個(gè)字節和當前串的前3個(gè)字節相同(稍后我們就可以看到這種說(shuō)法不準確,這里是為了說(shuō)明方便),我們可以找到那個(gè)串,做進(jìn)一步比較,看到底能有多長(cháng)的匹配。

  我們現在來(lái)說(shuō)明一下,相同的三個(gè)字節,通過(guò)哈希函數得到的ins_h必然是相同的。而不同的三個(gè)字節,通過(guò)哈希函數有沒(méi)有可能得到同一個(gè)ins_h,我沒(méi)有對這個(gè)哈希函數做研究,并不清楚,不過(guò)一般的哈希函數都是這樣的,所以極大可能這里的也會(huì )是這種情況,即不同的三個(gè)字節,通過(guò)哈希函數有可能得到同一個(gè)ins_h,不過(guò)這并不要緊,我們發(fā)現有可能是匹配串之后,還會(huì )進(jìn)行串的比較。

  一個(gè)文件中,可能有很多個(gè)串的頭三個(gè)字節都是相同的,也就是說(shuō)他們計算得到的ins_h都是相同的,如何能保證找到他們中的每一個(gè)串呢?gzip使用一個(gè)鏈把他們鏈在一起。gzip每次把當前串的位置插入head的當前串頭三個(gè)字節算出的ins_h處時(shí),都會(huì )首先把原來(lái)的head[ins_h]的值,保存到一個(gè)叫prev的數組中,保存的位置就在現在的strstart處。這樣當以后某處的當前串計算出ins_h,發(fā)現head[ins_h]不空時(shí),就可以到prev[ head[ins_h] ]中找到更前一個(gè)的頭三個(gè)字節相同的串的位置。對此我們舉例說(shuō)明。

  例,串
   0abcdabceabcfabcg
   ^^^^^^^^^^^^^^^^^
   01234567890123456

  整個(gè)串被壓縮程序處理之后。

  abc算出ins_h。
  這時(shí)的head[ins_h]中為 13,"abcg"的開(kāi)始位置。
  這時(shí)prev[13]中為 9,即"abcfabcg"的開(kāi)始位置。
  這時(shí)prev[9]中為 5,即"abceabcfabcg"的開(kāi)始位置。
  這時(shí)prev[5]中為 1,即"abcdabceabcfabcg"的開(kāi)始位置。
  這時(shí)prev[1]中為 0。

  我們看到所有頭三個(gè)字母為abc的串,被鏈在了一起,從head可以一直找下去,直到找到0。

  現在我們也就知道了,三個(gè)字節通過(guò)哈希函數計算得到同一ins_h的所有的串被鏈在了一起,head[ins_h]為鏈頭,prev數組中放著(zhù)的更早的串。這也就是headprev名稱(chēng)的由
  來(lái)。

   gzip尋找匹配串的另外一個(gè)值得注意的實(shí)現是,延遲匹配。會(huì )進(jìn)行兩次嘗試。比如當前串為str,那么str發(fā)生匹配以后,并不發(fā)生壓縮,還會(huì )對str 1串進(jìn)行匹配,然后看哪種
  匹配效果好。

  例子 ...
從這個(gè)例子中我們就看到了做另外一次嘗試的原因。如果碰到的一個(gè)匹配就使用了的話(huà),可能錯過(guò)更長(cháng)匹配的機會(huì )?,F在做兩次會(huì )有所改善。

   ...

   2.2 問(wèn)題討論

  我在這里對gzip壓縮算法做出了一些說(shuō)明,是希望可以和對gzip或者壓縮解壓縮感興趣的朋友進(jìn)行交流。
  我對gzip的了解要比這里說(shuō)的更多一些,也有更多的例子。如果哪位朋友愿意對下面的問(wèn)題進(jìn)行研究,以及其他壓縮解壓縮的問(wèn)題進(jìn)行研究,來(lái)這里http://jiurl.cosoft.org.cn/forum/ 和我交流的話(huà),我也愿意就我知道的內容進(jìn)行更多的說(shuō)明。

  下面是幾個(gè)問(wèn)題

  這種匹配算法,即用3個(gè)字節(最小匹配)來(lái)計算一個(gè)整數,是否比用串比較來(lái)得高效,高效到什么程度。

  哈希函數的討論。不同的三個(gè)字節,是否可能得到同一個(gè)ins_h。ins_h和計算它的三個(gè)字節的關(guān)系。

  幾次延遲嘗試比較好?

  用延遲,兩次嘗試是否對壓縮率的改善是非常有限的?

  影響lz77壓縮率的因素。

  壓縮的極限。

   2.3 ...

   3 gzip源碼分析

   main() 中調用函數 treat_file() 。
   treat_file() 中打開(kāi)文件,調用函數 zip()。注意這里的 work 的用法,這是一個(gè)函數指針。
   zip() 中輸出gzip文件格式的頭,調用 bi_init,ct_init,lm_init,
  其中在lm_init中將 head 初始化清0。初始化strstart0。從文件中讀入64KB的內容到window緩沖區中。
  由于計算strstart=0時(shí)的ins_h,需要0,1,2這三個(gè)字節和哈希函數發(fā)生關(guān)系,所以在lm_init中,預讀0,1兩個(gè)字節,并和哈希函數發(fā)生關(guān)系。

  然后lm_init調用 deflate()。
   deflate() gzipLZ77的實(shí)現主要deflate()中。
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
deflate算法總結
gzip原理與實(shí)現(非常好)
hlist哈希鏈表
如何實(shí)現一個(gè)簡(jiǎn)單的區塊鏈?區塊鏈偽技術(shù)簡(jiǎn)介(二)
Hash Table哈希表和Hash List哈希鏈表的知識匯總
c語(yǔ)言怎么從入門(mén)到精通,有什么推薦的方法和資料?
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久