數據結構與算法-赫夫曼樹

赫夫曼樹

過去我們小學、中學一般考試都是用百分制來表示學科成績的。這帶來了一個弊端,就是很容易讓學生、家長,甚至老師自己都以分取人,讓分數代表了一切。有時想想也對,90分和95分也許就只是一道題目對錯的差距,但卻讓兩個孩子可能受到完全不同的待遇,這并不公平。于是在如今提倡素質教育的背景下,我們很多的學科,特別是小學的學科成績都改作了優秀、良好、中等、及格和不及格這樣模糊的詞語,不再通報具體的分數。

不過對于老師來講,他在對試卷評分的時候,顯然不能憑感覺給優良或及格不及格等成績,因此一般都還是按照百分制算出每個學生的成績后,再根據統一的標準換算得出五級分制的成績。比如下面的代碼就實現了這樣的轉換。

if (a < 60)
    b = "不及格";
else if (a < 70)
    b = "及格";
else if (a < 80)
    b = "中等";
else if (a < 90)
    b = "良好";
else
    b = "優秀";

上面的代碼粗略看沒什么問題,可是通常都認為,一張好的考卷應該是讓學生成績大部分處于中等或良好的范圍,優秀和不及格都應該較少才對。而上面這樣的程序,就使得所有的成績都需要先判斷是否及格,再逐級而上得到結果。輸入量很大的時候,其實算法是有效率問題的。

如果在實際的學習生活中,學生的成績在5個等級上的分布規律如下圖所示

image-20200505214324174

那么70分以上大約占總數80%的成績都需要經過3次以上的判斷才可以得到結果,這顯然不合理。

有沒有好一些的辦法,仔細觀察發現,中等成績(70~79分之間)比例最高,其次是良好成績,不及格的所占比例最少。我們把圖6-12-2這棵二叉樹重新進行分配。改成如下圖的做法試試看。

image-20200505214400687

赫夫曼樹定義與原理

我們先把這兩棵二叉樹簡化成葉子結點帶權的二叉樹(注:樹結點間的邊相關的數叫做權Weight),如圖下所示。其中A表示不及格、B表示及格、C表示中等、D表示良好、E表示優秀。每個葉子的分支線上的數字就是剛才我們提到的五級分制的成績所占百分比。

image-20200505214754902

赫夫曼大叔說,從樹中一個結點到另一個結點之間的分支構成兩個結點之間的路徑,路徑上的分支數目稱做路徑長度。上圖的二叉樹a中,根結點到結點D的路徑長度就為4,二叉樹b中根結點到結點D的路徑長度為2。樹的路徑長度就是從樹根到每一結點的路徑長度之和。二叉樹a的樹路徑長度就為1+1+2+2+3+3+4+4=20。二叉樹b的樹路徑長度就為1+2+3+3+2+1+2+2=16。

帶權結點路勁的計算

“如果考慮到帶權的結點,結點的帶權的路徑長度為從該結點到樹根之間的路徑長度與結點上權的乘積。樹的帶權路徑長度為樹中所有葉子結點的帶權路徑長度之和。假設有n個權值{w1,w2,...,wn},構造一棵有n個葉子結點的二叉樹,每個葉子結點帶權wk,每個葉子的路徑長度為lk,我們通常記作,則其中帶權路徑長度WPL最小的二叉樹稱做赫夫曼樹。也有不少書中也稱為最優二叉樹,我個人覺得為了紀念做出巨大貢獻的科學家,既然用他們的名字命名,就應該要堅持用他們的名字稱呼,哪怕“最優”更能體現這棵樹的品質也應該只作為別名。

有了赫夫曼對帶權路徑長度的定義,我們來計算一下上圖這兩棵樹的WPL值。

二叉樹a的WPL=5×1+15×2+40×3+30×4+10×4=315

注意:這里5是A結點的權,1是A結點的路徑長度,其他同理。

二叉樹b的WPL=5×3+15×3+40×2+30×2+10×2=220

這樣的結果意味著什么呢?如果我們現在有10000個學生的百分制成績需要計算五級分制成績,用二叉樹a的判斷方法,需要做31500次比較,而二叉樹b的判斷方法,只需要22000次比較,差不多少了三分之一量,在性能上提高不是一點點。

赫夫曼樹的構建

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

2.取頭兩個最小權值的結點作為一個新節點N1的兩個子結點,注意相對較小的是左孩子,這里就是A為N1的左孩子,E為N1的右孩子,如下圖所示。新結點的權值為兩個葉子權值的和5+10=15。

image-20200505215904388

3.將N1替換A與E,插入有序序列中,保持從小到大排列。即:N115,B15,D30,C40。

4.重復步驟2。將N1與B作為一個新節點N2的兩個子結點。如下圖所示。N2的權值=15+15=30。

image-20200505220014279

5.將N2替換N1與B,插入有序序列中,保持從小到大排列。即:N230,D30,C40。

6.重復步驟2。將N2與D作為一個新節點N3的兩個子結點。如下圖所示。N3的權值=30+30=60。

image-20200505220119727

7.將N3替換N2與D,插入有序序列中,保持從小到大排列。即:C40,N360。

8.重復步驟2。將C與N3作為一個新節點T的兩個子結點,如圖6-12-8所示。由于T即是根結點,完成赫夫曼樹的構造。

image-20200505220205273

此時的二叉樹的帶權路徑長度WPL=40×1+30×2+15×3+10×4+5×4=205。與上面的二叉樹b的WPL值220相比,還少了15。顯然此時構造出來的二叉樹才是最優的赫夫曼樹。

通過剛才的步驟,我們可以得出構造赫夫曼樹的赫夫曼算法描述。

  1. 根據給定的n個權值{w1,w2,...,wn}構成n棵二叉樹的集合F={T1,T2,...,Tn},其中每棵二叉樹Ti中只有一個帶權為wi根結點,其左右子樹均為空。
  2. 在F中選取兩棵根結點的權值最小的樹作為左右子樹構造一棵新的二叉樹,且置新的二叉樹的根結點的權值為其左右子樹上根結點的權值之和。
  3. 在F中刪除這兩棵樹,同時將新得到的二叉樹加入F中。
  4. 重復2和3步驟,直到F只含一棵樹為止。這棵樹便是赫夫曼樹。”

赫夫曼編碼

比如我們有一段文字內容為“BADCADFEED”要網絡傳輸給別人,顯然用二進制的數字(0和1)來表示是很自然的想法。我們現在這段文字只有六個字母ABCDEF,那么我們可以用相應的二進制數據表示,如下圖所示。

image-20200505220649854

這樣真正傳輸的數據就是編碼后的“001000011010000011101100100011”,對方接收時可以按照3位一分來譯碼。如果一篇文章很長,這樣的二進制串也將非常的可怕。而且事實上,不管是英文、中文或是其他語言,字母或漢字的出現頻率是不相同的,比如英語中的幾個元音字母“ae i o u”,中文中的“的 了 有 在”等漢字都是頻率極高。

假設六個字母的頻率為A 27,B 8,C 15,D15,E 30,F 5,合起來正好是100%。那就意味著,我們完全可以重新按照赫夫曼樹來規劃它們。

下圖左圖為構造赫夫曼樹的過程的權值顯示。右圖為將權值左分支改為0,右分支改為1后的赫夫曼樹。

image-20200505220908436

此時,我們對這六個字母用其從樹根到葉子所經過路徑的0或1來編碼,可以得到如下圖所示這樣的定義。

image-20200505220942005

我們將文字內容為“BADCADFEED”再次編碼,對比可以看到結果串變小了。

  • 原編碼二進制串:001000011010000011101100100011(共30個字符)
  • 新編碼二進制串:1001010010101001000111100(共25個字符)

因此在解碼時,還是要用到赫夫曼樹,即發送方和接收方必須要約定好同樣的赫夫曼編碼規則。

當我們接收到1001010010101001000111100時,由約定好的赫夫曼樹可知,1001得到第一個字母是B,接下來01意味著第二個字符是A,

一般地,設需要編碼的字符集為{d1,d2,...,dn},各個字符在電文中出現的次數或頻率集合為{w1,w2,...,wn},以d1,d2,...,dn作為葉子結點,以w1,w2,...,wn作為相應葉子結點的權值來構造一棵赫夫曼樹。規定赫夫曼樹的左分支代表0,右分支代表1,則從根結點到葉子結點所經過的路徑分支組成的0和1的序列便為該結點對應字符的編碼,這就是赫夫曼編碼。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,797評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,179評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,628評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,642評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,444評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,948評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,040評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,185評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,717評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,602評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,794評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,045評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,418評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,414評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,750評論 2 370