1. 程式人生 > >Android版資料結構與演算法(七):赫夫曼樹

Android版資料結構與演算法(七):赫夫曼樹

近期忙著新版本的開發,此外正在回顧C語言,大部分時間沒放在資料結構與演算法的整理上,所以更新有點慢了,不過既然寫了就肯定盡力將這部分完全整理好分享出來。

言歸正傳,開啟本篇的正文。

一、什麼是赫夫曼樹

給定n個權值作為n個葉子結點,構造一棵二叉樹,若該樹的帶權路徑長度達到最小,稱這樣的二叉樹為最優二叉樹,也稱為哈夫曼樹(Huffman Tree)。哈夫曼樹是帶權路徑長度最短的樹,權值較大的結點離根較近。

以上來自百度百科,相信完全不瞭解的同學看完肯定一頭霧水,啥玩意,這麼多術語,權值?樹的帶權路徑長度?都是什麼鬼?別急,下面一一解釋。

二、赫夫曼樹中術語解釋

路徑:從樹中一個結點到另一個結點之間的分支構成兩個結點之間的路徑。

結點路徑長度:一個結點到另一個結點之間路徑上分枝數目稱作路徑長度。

  比如上圖中根結點到A結點路徑長度為3

樹的路徑長度:樹根結點每一結點的路徑長度之和稱作樹的路徑長度之和。這裡是每一結點,而不僅僅是葉子結點。

  比如上圖樹的路徑長度為:1+1+2+2+2+2+3+3 = 16

結點權值:將樹中的結點賦予一個有意義的數,稱為該結點的權值。

結點的帶權路徑長度:該結點樹根之間的路徑長度與該結點權值乘機叫做結點的帶權路徑長度。

  比如上圖中A結點帶權路徑長度為:3 * 5 = 15

樹的帶權路徑長度:樹中所有葉子結點的帶權路徑長度之和叫作樹的帶權路徑長度。

  上圖樹的帶權路徑長度為:3*5+15*3+40*2+30*2+10*2=220

樹的帶權路徑長度可計作WPL,赫夫曼樹就是WPL最小的的二叉樹。

三、赫夫曼樹的建立

瞭解了基本的概念之後我們繼續看下赫夫曼樹到底怎麼建立呢?以下就直接說建立流程了。

比如我們有以下幾個結點資訊:A5(A代表結點名字,5代表其權值),B15,C40,D30,E10。

構造赫夫曼樹流程如下:

(1)先把有權值的葉子結點從小到大排序成一個有序序列:A5,E10,B15,D30,C40。

(2)取頭兩個最小權值的結點作為新結點M1的兩個子結點,其中權值小的結點在左側,權值大的在右側。即A5為M1的左孩子,E10為M1的右孩子,M1結點權值為兩個子結點權值的和15,即M15,如圖:

 (3)新結點M15替換A5與E10結點,插入有序序列中,依然保持從小到大排序:M15,B15,D30,C40。

 (4)重複步驟(2),將M15與B15作為新結點P的左右孩子,P的權值為30,如圖:

(5) P30替換M15,B15插入有序序列中依然保持從小到大順序:P30,D30,C40。

(6)重複步驟(2),將P30,D30作為新結點T的左右孩子,T結點權值為60,如圖:

 (7)T60替換P30,D30插入有序序列,依然保持從小到達排序:C40,T60。

 (8)重複步驟(2),C40,T60作為新結點N的左右孩子,N權值為100,N即為根結點,完成赫夫曼樹的構建,如圖:

 到此,赫夫曼樹就已經構建完成,其WPL為:WPL=40*1+30*2+15*3+5*4+10*4=205

 整個構建過程核心思想就是讓權值小的結點距離根結點遠,權值大的距離根結點近一些。

四、赫夫曼編碼

赫夫曼老爺子研究最優樹可不是僅僅為了構建就完事了,肯定有其用處的,赫夫曼樹就是為了解決當年遠距離通訊的資料最優化問題。

比如我們有一段文字"EDEFABAC..."要進行網路傳輸,一般我們都會選擇二進位制方式傳輸,這段文字只包含6個字母:ABCDEF,那麼用二進位制表示每個字母需要用3位表示,如圖:

字母 A B C D E F
二進位制表示 000 001 010 011 100 101

這段文字中各字母出現頻率分別為A 20, B 10, C 15, D 15, E 25, F 15,正好100%。

這樣就可以按照赫夫曼樹思想來重新規劃各個字母的編碼,頻率即是各個字母的權重,構建赫夫曼樹, 並且將左孩子權重改為0,右孩子改為1,得到下圖:

然後我們對各個字母重新編碼,編碼規則為:從根結點到葉子結點經過路徑的0和1來編碼,重新編碼後如下:

字母 A B C D E F
二進位制表示 10 11110 11111 1110 0 110

將"EDEFABAC"這段文字進行編碼的前後比較:

原編碼:100011100101000001000010 (24個字元) 

新編碼:01110011010111101011111        (23個字元)

編碼後資料被壓縮了,這裡大家可以覺得才減少一個字元啊,實際情況不可能只有這幾個字元的,一個文字會包含很多的字元,這樣就可以被壓縮很多空間,更利於資料的傳輸。

 五、總結

以上介紹了赫夫曼樹以及其使用場景之一(資料的壓縮),赫夫曼樹原理還有很多其餘用處,學習赫夫曼樹更多的是要體會其思想,好了,本篇到此為止,下一篇二叉排序樹的介紹以及java程式碼的實現。