現在,我們經常會使用壓縮和解壓縮軟件來處理文檔,因為它除了可以減少文檔在磁盤上的空間外,還有重要的一點,就是我們可以在網絡上一壓縮的形式傳輸大量數據,是的保存和傳遞都更加高效。
那么壓縮而不出錯是如何做到的呢?簡單說,就是把我們要壓縮的文本進行重新編碼,今天我們就介紹一種最基本的壓縮編碼方法——哈夫曼編碼。
在介紹哈夫曼編碼之前,我們必須的介紹哈夫曼 樹,首先,我們來看一個例子:
現在,有的課程,老師通常會按照以下方法,將學生的成績將其分為不及格,及格,中等,良好和優秀這樣的等級。
但是,如果在實際生活中,學生的成績在5個等級上的分布規律如下:
那么70分以上約占總數80%的成績都需要經過3次以上的判斷才可以得到結果,這顯然不合理。
如是,我們根據上面的比例對這顆二叉樹進行重新分配,改成如下結果:
效率應該更高一些,但是到底高多少,以及這顆二叉樹是如何設計的,我們來看看這個過程,也就是哈夫曼樹的構造過程。
哈夫曼樹定義與原理
我們先把上面兩棵樹簡化成葉子結點帶權的二叉樹,如下圖所示,其中A表示不及格,B表示及格,C表示中等,D表示良好,E表示優秀。
那么,從上圖我們可以得到幾個概念:
(1)路徑長度:從樹中一個結點到另一個結點之間的分支構成兩個結點之間的路徑,路徑上的分支數目稱作路徑長度,例如二叉樹a中,根節點到結點D的路徑長度為4.
(2)樹的路徑長度:指從樹根到每一個結點的路徑長度之和。例如二叉樹a的路徑長度就是1+1+2+2+3+3+4+4=20.
(3)帶權路徑長度:結點的帶權路徑長度為從該節點到樹根之間的路徑長度與結點上權的乘積。
(4)樹的帶權路徑長度:樹中所有葉子結點的帶權路徑長度之和,例如二叉樹a的帶權路徑長度為:5*1+15*2+40*3+30*4+10*4=315.
(5)哈夫曼樹:指帶權路徑長度最小的二叉樹為哈夫曼樹。
哈夫曼樹的構造過程及算法如下:
因此,上述成績的哈夫曼樹的構造過程為下:
.........
哈夫曼編碼
如果我們想要有一段文字內容“BADCADFEED”,通過網絡傳輸給別人,顯然用二進制的數字(0和1)來表示是很自然的想法,因此,我們可以用相應的二進制數據表示:
那么要傳輸的數據編碼以后為“0010000011010000011101100100011”,共30個字符。
但是,在英文中每個字母出現的頻率是不一樣的,例如“a e i o u”幾個元音字母出現頻率很高,那么我們完全可是使用哈夫曼樹來重新規划他們,假如六個字母出現的頻率為A 27,B 8,C 15,D 15,E 30, F 5.那么我們可以構造如下的哈夫曼樹:
在上圖中,我們將權值左分支改為0,右分支改為1。得到如下的哈夫曼樹:
我們對這六個字母用其從樹根到葉子所經過的路徑的0和1來編碼,可以得到如下所示的定義:
我們對“BADCADFEED”再次編碼為“1001010010101001000111100”,共17個字符,因此節約了17%的傳輸成本。