有趣的赫夫曼樹

滴水微瀾發表於2018-11-23
美國有個數學家叫赫夫曼,60年前他根據資料的使用概率,發明了一個二叉樹叫赫夫曼樹。
這個赫夫曼樹被用在了資料壓縮上,被稱為赫夫曼編碼,這是後來壓縮的基礎。
 
他解決的問題主要思想是:根據元素出現的概率,獲得最優解。
 
舉例如下:
學生考試成績出來後,會根據考試成績分等級,極優秀,優秀,中等,及格,不及格。如果我們按照普通邏輯進行判斷時,通常是:
 
    if (Score < 60) {
        printf("不及格");
    } else if (Score < 70) {
        printf("及格");
    } else if (Score < 80) {
        printf("中等");
    } else if (Score < 90) {
        printf("優秀");
    } else if (Score < 100) {
        printf("極優秀");
    }
但是按照分數的分佈概率,優秀:30%,中等:40%,及格:15%,極優秀:10%,不及格:5%
如果先判斷優秀,中等,再判斷極優秀,極優秀,不及格,則可以提高很多效率。
赫夫曼樹就是根據概率來生成的二叉樹。
轉換成二叉樹區別如下:
 
從根節點出發,遍歷每一個葉子節點,是的到達節點時走的連結樹乘以節點(nodeLinkNum * weight)對應的權重之和最小
如:
sum = 1*5+2*15+3*40+4*30+4*10
顯然,左圖和右圖總和不一樣,左圖的和大於右圖.
 
那給你一組數字,怎麼構造一個赫夫曼樹呢?
1.先把所有的資料節點,從小到大依次排列,成為一個有序列表
2.取出前面兩個節點,讓這兩個節點的權重資料相加得到一個和,令這個和為根節點,這個兩個節點的小的為其左孩子,大的為其右孩子
3.令這個和節點替換掉前面的兩個節點,並重新排序,生成一個有序列表
4.不斷重複第二步,第三步。直到所有的節點都被用完,得到一個排序結果,此時生成的二叉樹,就是赫夫曼樹。
 
 
赫夫曼樹的實際應用:壓縮資料
資料在計算機的表示形式是0,1,那麼一串字串的表示是怎麼樣的呢
例如ABCDEF編碼如下:
那麼要表示字串“BADCADFEED”的二進位制為:“001000011010000011101100100011”。
但是ABCDEF做為基本字元,在這串字串中的出現概率是不一樣的,那麼我們是否可以以概率做為字元權重,對字元生成赫夫曼樹呢
 
假設六個字母的頻率為A 27,B 8,C 15,D15,E 30,F 5,合起來正好是100%。那就意味著,我們完全可以重新按照赫夫曼樹來規劃它們。
 
 
將權值左分支改為0,右分支改為1後的赫夫曼樹。
 
根據重新編碼後為:
1001010010101001000111100(共25個字元)
而原來的字元編碼為:
“001000011010000011101100100011”(共30個字元)
壓縮了近17%
 
解壓時,按照同樣的規則,還原原字串。
 
 

相關文章