有趣的赫夫曼樹
阿新 • • 發佈:2018-11-23
bcd 根節點 數字 sum obj 基本 重復 adf 表示 美國有個數學家叫赫夫曼,60年前他根據數據的使用概率,發明了一個二叉樹叫赫夫曼樹。
這個赫夫曼樹被用在了數據壓縮上,被稱為赫夫曼編碼,這是後來壓縮的基礎。
他解決的問題主要思想是:根據元素出現的概率,獲得最優解。
舉例如下:
學生考試成績出來後,會根據考試成績分等級,極優秀,優秀,中等,及格,不及格。如果我們按照普通邏輯進行判斷時,通常是:
但是按照分數的分布概率,優秀: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%
解壓時,按照同樣的規則,還原原字符串。
if (Score < 60) { printf("不及格"); } else if (Score < 70) { printf("及格"); } else if (Score < 80) { printf("中等"); } else if (Score < 90) { printf("優秀"); } else if (Score < 100) { printf("極優秀"); }
有趣的赫夫曼樹