本博客的代碼的思想和圖片參考:好大學慕課浙江大學陳越老師、何欽銘老師的《數據結構》
哈夫曼編碼問題
1 引子
1.1
將百分制的考試成績轉換成五分制的成績,程序如下:
if( score < 60 ) grade =1;
else if( score < 70 ) grade =2;
else if( score < 80 ) grade =3;
else if( score < 90 ) grade =4;
else grade =5;
那么上面這個其實是一棵判斷樹:
我們發現,在這個判斷樹中,60分以下的需要查找一次,60-69的需要查找兩次
70-79需要查找三次,80-89的需要查找四次,90以上的需要查找五次
如果全部的分數集中在70—80之間,那么這棵樹就不夠優化。
1.2
如果我們考慮學生的成績分布情況,如下表所示:
分數段 |
0-59 |
60-69 |
70-79 |
80-89 |
90以上 |
比例 |
0.05 |
0.15 |
0.40 |
0.30 |
0.10 |
根據上面的判斷樹和學生成績的分布情況,那么我們計算平均的查找效率:
0.05*1+0.15*2+0.40*3+0.30*4+0.10*4=3.15
如何我們重新設計程序,讓頻率高優先判定,那么就會減少判定的次數,我們重新設計判斷程序和判斷樹
if(score<80){
if(score<70){
if(score<60){
grade=1;
}else{
grade=2;
}
}else{
grade=3;
}
}else{
if(score<90){
grade=4;
}else{
grade=5;
}
}
這樣的判斷樹就如下所示:
分數段 |
0-59 |
60-69 |
70-79 |
80-89 |
90以上 |
比例 |
0.05 |
0.15 |
0.40 |
0.30 |
0.10 |
那么我們再根據判斷樹和分數的頻率來計算平均查找效率:
0.05*3+0.15*3+0.4*2+0.3*2+0.10*2=2.2
平均查找效率明星變高了。
思考:如果根據節點的頻率不同,構造更高效率的搜索樹
2 哈夫曼樹
2.1 定義
定義:帶權路徑長度(WPL):設二叉樹有n個葉子節點,每個節點帶有權值,從根節點到每個葉子節點的長度為,則每個葉子的帶權路徑之和為
最優二叉樹或者哈夫曼數:WPL值最小
2.2 例子
現有五個葉子節點,他們的權值為{1,2,3,4,5},用此權值序列可以構造多個不同形狀的二叉樹。
3哈夫曼編碼
3.1例子
給定一段字符串,如何對字符進行編碼,可以使得該字符串的
存儲空間最少?
[例] 假設有一段文本,包含58個字符,並由以下7個字符構: a,
s, t,空格( sp),換行( nl);這7個字符出現的次數不同。如
這7個字符進行編碼,使得總編碼空間最少?
【 分析】
( 1)用等長ASCII編碼: 58 ×8 = 464位;
( 2)用等長3位編碼: 58 ×3 = 174位;
( 3)不等長編碼:出現頻率高的字符用的編碼短些,出現頻率低
的字符則可以編碼長些?
3.2如何進行不等長編碼
3.2.1 編碼的二義性
例如:
a:1
e:0
s:10
t:11
那么1011是什么編碼
aeza:1101
aet:1101
st:1011
這樣就產生了編碼的二義性。
那么如何避免二義性呢?使用前綴碼
前綴碼(prefix code):任何字符的編碼都不是另一個字符編碼的前綴,就可以無二義的解碼
3.2.2 使用二叉樹進行編碼
使用二叉樹進行編碼:
a):左右分支表示0,1
b)字符只在葉子節點上
四個字符的頻率:
a:4,u:1,x:2,z:1
那么我們可以使用二叉樹進行編碼
可以看出,使用二叉樹進行哈夫曼編碼可以減少編碼的總長度
3.3 哈夫曼編碼的一個具體的例子
該例子出自於:慕課浙江大學數據結構陳越老師何欽銘老師
需求:
二叉樹的哈夫曼編碼