天天看點

算法解析:哈夫曼(huffman)壓縮算法前言

前言

本篇将介紹哈夫曼壓縮算法(Huffman compression)

哈夫曼壓縮算法(Huffman compression)

衆所周知,計算機存儲資料時,實際上存儲的是一堆0和1(二進制)。

如果我們存儲一段字元:ABRACADABRA!

那麼計算機會把它們逐一翻譯成二進制,如A:01000001;B: 01000010; !: 00001010.

每個字元占8個bits, 這一整段字元則至少占12*8=96 bits。

但如果我們用一些特殊的值來代表這些字元,如:

算法解析:哈夫曼(huffman)壓縮算法前言

圖中,0代表A; 1111代表B;等等。此時,存儲這段字元隻需30bits,比96bits小多了,達到了壓縮的目的。

我們需要這麼一個表格來把原資料翻譯成特别的、占空間較少的資料。同時,我們也可以用這個表格,把特别的資料還原成原資料。

首先,為了避免翻譯歧義,這個表格需滿足一個條件:任何一個字元用的值都不能是其它字元的字首。

我們舉個反例:A: 0; B: 01;這裡,A的值是B的值的字首。如果壓縮後的資料為01xxxxxx,x為0或者1,那麼這個資料應該翻譯成A1xxxxxx, 還是Bxxxxxxx?這樣就會造成歧義。

然後,不同的表格會有不同的壓縮效果,如:

算法解析:哈夫曼(huffman)壓縮算法前言

這個表格的壓縮效果更好。

那麼我們如何找到最好的表格呢?這個我們稍後再講。

為了友善閱讀,這個表格是可以寫成一棵樹的:

算法解析:哈夫曼(huffman)壓縮算法前言

這棵樹的節點左邊是0,右邊是1。任何含有字元的節點都沒有非空子節點。(即上文提及的字首問題。)

這棵樹是在壓縮的過程中建成的,這個表格是在樹形成後建成的。用這個表格,我們可以很簡單地把一段字元變成壓縮後的資料,如:

原資料:ABRACADABRA!

表格如上圖。

令壓縮後的資料為S;

第一個字元是A,根據表格,A:11,故S=11;

第二個字元是B,根據表格,B:00,故S=1100;

第三個字元是R,根據表格,R:011,故S=1100011;

如此類推,讀完所有字元為止。

壓縮搞定了,那解壓呢?很簡單,跟着這棵樹讀就行了:

算法解析:哈夫曼(huffman)壓縮算法前言

壓縮後的資料S=11000111101011100110001111101

記住,讀到1時,往右走,讀到0時,往左走。

令解壓後的字元串為D;

從根節點出發,第一個數是1,往右走:

算法解析:哈夫曼(huffman)壓縮算法前言

第二個數是1,往右走:

算法解析:哈夫曼(huffman)壓縮算法前言

讀到有字元的節點,傳回此字元,加到字元串D裡。D:A;

傳回根節點,繼續讀。

算法解析:哈夫曼(huffman)壓縮算法前言

第三個數是0,往左走:

算法解析:哈夫曼(huffman)壓縮算法前言

第四個數是0,往左走:

算法解析:哈夫曼(huffman)壓縮算法前言

讀到有字元的節點,傳回此字元,加到字元串D裡。D:AB;

傳回根節點,繼續讀。

第五個數是0,往左走:

算法解析:哈夫曼(huffman)壓縮算法前言

第六個數是1,往右走:

算法解析:哈夫曼(huffman)壓縮算法前言

第七個數是1,往右走:

算法解析:哈夫曼(huffman)壓縮算法前言

讀到有字元的節點,傳回此字元,加到字元串D裡。D:ABR;

傳回根節點,繼續讀。

如此類推,直到讀完所有壓縮後的資料S為止。

壓縮與解壓都搞定了之後

  我們需要先把原資料讀一遍,并把每個字元出現的次數記錄下來。如:

ABRACADABRA!中,A出現了5次;B出現了2次;C出現了1次;D出現了1次;R出現了2次;!出現了1次。

理論上,出現頻率越高的字元,我們給它一個占用空間越小的值,這樣,我們就可以有最佳的壓縮率

由于哈夫曼壓縮算法這塊涉及内容較多 ,文章篇幅很長;全文全方面講解了Compose布局的各方面知識。更多Android前言技術進階,我自薦一套 《完整的Android的資料,以及一些視訊課講解》

 

有需要的同學可以在評論區下方留言 “進階” 或 “筆記” 或者直接私信我 即可免費擷取

算法解析:哈夫曼(huffman)壓縮算法前言
算法解析:哈夫曼(huffman)壓縮算法前言

最後我想說:

對于程式員來說,要學習的知識内容、技術有太多太多,要想不被環境淘汰就隻有不斷提升自己,從來都是我們去适應環境,而不是環境來适應我們

技術是無止境的,你需要對自己送出的每一行代碼、使用的每一個工具負責,不斷挖掘其底層原理,才能使自己的技術升華到更高的層面

Android 架構師之路還很漫長,與君共勉