huffman演算法是一種基於統計的壓縮方法。它的本質就是對文字檔案中的字元進行重新編碼,對於使用頻率越高的字元,其編碼也越短。但是任何2個字元的編碼,是不能出現向前包含的。也就是說字元a的編碼的前段,不可能為字元b的編碼。經過編碼後的文字檔案,主要包含2個部分:huffman碼表部分和壓縮內容部分。解壓縮的時候,先把huffman碼表取出來,然後對壓縮內容部分各個字元進行逐一解碼,形成原始檔。
由此可見,使用huffman演算法的關鍵是形成huffman碼表。怎樣才能生成乙個「使用頻率越高的字元,其編碼也越短」的碼表呢?這裡就要用到 huffman樹的資料結構。當把一棵huffman樹生成後,碼表也就生成了。以下舉例說明,假定我們的原始文字為"abcbbcccc"
huffman樹生成步驟:
1.掃瞄原始檔,對字元頻率進行統計。
對於我們的樣例,統計結果是:a:1 b:3 c:5 (按頻率公升序排列)
2.從上述佇列中取出頻率最低的2個節點,合併成乙個頻率為2節點頻率之和的樹枝節點x,加入到原佇列中,加入後,繼續保持佇列按頻率公升序排列.
3.重複步驟2,直到佇列中只有乙個節點。
4.這樣,我們就形成了一棵huffman樹。葉子節點為字元,從樹根節點到葉子節點的路徑即為該字元的huffman編碼。從乙個節點導航到其左孩子,該段路徑為0,導航到右孩子,該段路徑為1.所以,a字元的編碼就是00,b字元的編碼為01,c字元的編碼為1,符合"使用頻率越高的字元,編碼越短"的要求。理論論證過程見《演算法導論》p233
5.huffman碼表生成後,原文本"abcbbcccc"就變成了0001101011111的位串,按每個字元占用2個byte計算,大小由原來的18個位元組(9*2),共144個bit,變成了13個bit,2個位元組。達到了壓縮的目的。
解壓縮過程:
解壓縮也分成2部分進行,首先是根據壓縮檔案中的huffman碼表,在記憶體中生成一棵huffman樹,然後,根據huffman樹,對壓縮內容進行解壓縮。比如如果壓縮內容為位串0001101011111,那麼從樹根節點起,因為第乙個bit為0,先轉向左子樹,第二個bit為0,再轉向左子樹,到達葉子a,所以解碼出來的第乙個字元就是a,每次解壓乙個字元,都從根節點起,根據bit流,向左或向右轉,直到到達葉子節點,也就是解壓出來的字元。一直重複此過程,直到所有的字元都被解壓縮。
使用huffman壓縮演算法對文字檔案壓縮後,就形成了乙個壓縮檔案,該壓縮檔案包含2部分,一部分為huffman碼表,也就是huffman 樹,第二部分為根據碼表生成的內容位串。如何設計huffman樹的儲存格式呢?本文採用從上到下,從左到右分層遍歷節點,順序儲存的方式。如下圖:
也就是說,對於前述的huffman樹,其持久化形式為:0xfffe 0xfffe 0x0063 0x0061 0x0062,其中0xfffe代表樹枝節點,而0x0061,0x0062,0x0063分別為a,b,c的unicode碼。因為所有的樹枝節點的值都是0xfffe,所有樹枝節點都有2個孩子,節點排列方式是按從上到下,從左到右分層排列,所以能根據此持久化位元組陣列,把huffman樹在記憶體中重新生成。
另外為了公升級版本,嵌入了magic number和version。
貪心演算法 Huffman編碼
huffman編碼是資料壓縮常見的壓縮方法。即將不同概率出現的字元以不同長度的二進位制位進行編碼,概率出現的越高的字元使用長度越短的編碼,概率出現越低的字元使用長度越長的編碼。下面是對儲存字元出現概率的檔案charactorsheet.txt,每一行的左邊是字元出現的概率,單位是0.01,右邊是要編...
Huffman編碼演算法的實現
huffman樹中沒有度為1的節點。n0 n2 1 1棵樹有n個葉子節點的huffman樹共有2n 1個節點,故可儲存在大小為2n 1的一位陣列中。原因 求編碼需要從葉子節點出發走一條從葉子到根的路徑。weight parent lchild rchild 權值雙親節點下標左右 解碼需從根節點出發走...
Huffman樹與Huffman編碼
一.哈夫曼樹概念 路徑 祖先到節點之間的分支構成一條通往節點的路徑 路徑長度 路徑上分支的數目稱為路徑長度 節點的權 給樹中節點所設的物理意義的值 節點帶權路徑長度 從根到該點路徑長度與該點權值的乘機 huffman樹就是所有樹中每點帶權路徑加和最短的樹。二.huffman樹構造步驟 1.根據每個點...