表a、表b、表c、表D(按下圖底部的順序排列):字符編碼a000b 010c 100D 11字符編碼A00b010c11字符。編碼a0b 110c 10d 111字符編碼A01b 010c 0010d 10表3字符的四種不同編碼方案。
霍夫曼樹可用於構建壹種編碼方案,使消息的總編碼長度最小化。具體方法如下:設待編碼的字符集為{d1,d2,…,dn},它們在消息中出現的時間或頻率集為{w1,w2,…,wn},d1,d2,…,dn為葉節點,w1。右分支代表1,那麽從根節點到每個葉節點的路徑分支形成的0和1的序列就是該節點對應字符的編碼,我們稱之為霍夫曼編碼。
在霍夫曼編碼樹中,樹的加權路徑長度意味著每個字符的代碼長度與其出現次數的乘積之和,即消息的總代碼長度,因此霍夫曼樹構造的代碼是壹種不等長代碼,可以使消息的總代碼長度最短。
建立不等長碼時,需要使任壹字符的代碼不是另壹字符代碼的前綴,以保證解碼的唯壹性。例如,在表7.3(d)中的編碼方案中,字符A的代碼01是字符B的代碼010的前綴部分,因此代碼串0101001既是AAC代碼,也是ABD和BDA的代碼。因此,這樣的編碼不能保證解碼的唯壹性。
但是,如果使用霍夫曼樹進行編碼,則不會出現上述歧義問題。因為在霍夫曼樹中,每個字符節點都是壹個葉節點,它們不可能在從根節點到其他字符節點的路徑上,因此壹個字符的霍夫曼編碼不可能是另壹個字符的霍夫曼編碼的前綴,從而確保了解碼的模糊性。
下面討論實現霍夫曼編碼的算法。實現霍夫曼編碼的算法可以分為兩個部分:
(1)構造霍夫曼樹;
(2)找出霍夫曼樹上葉節點的編碼。
本質上,尋找霍夫曼碼意味著在建立的霍夫曼樹中,從葉節點開始,沿著節點的父鏈域回溯到根節點,每回溯壹步,都要經過霍夫曼樹的壹個分支,從而獲得壹個霍夫曼碼值。因為字符的霍夫曼碼是由從根節點到相應葉節點的路徑上的分支組成的0,1序列,所以首先獲得它。我們可以設置壹個結構數組HuffCode來存儲每個字符的霍夫曼編碼信息。數組元素的結構如下:bit start,其中組成位是壹個壹維數組,用於存儲字符的霍夫曼編碼,start表示編碼在數組位中的起始位置。因此,對於第I個字符,其霍夫曼代碼存儲在來自huff code【I】的組件中。huff code【I】。bit中的開始到n。
查找霍夫曼編碼程序段
const Maxleaf = 128;{定義葉節點的最大數量}
MaxNode = 255{定義最大節點數}
max bit = 10;{定義霍夫曼編碼的最大長度}
類型HCodeType =記錄
位:數組【0..整數的MaxBit 】;
start:整數;
結束;
……
程序HaffmanCode{生成霍夫曼代碼}
var HuffNode:array【0..HCodeType的MaxNode 】;
HuffCode:數組【0..HcodeType的MaxLeaf 】;
CD:hcode type;
I、j、c、p:整數;
開始
赫夫曼特裏(huff node);{構建霍夫曼樹}
對於i:=0到n-1做{查找每個葉節點的霍夫曼碼}
開始
CD . start:= n-1;c:= I;
赫夫德。父母;
而p & lt& gt0 do {從葉節點到根}
如果赫芬頓【p】。l child = c then CD . bit【CD . start】:= 0
else CD . bit【CD . start】:= 1;
dec(CD . start);c:= p;
赫夫德。父母;
結束;
for j:= CD . start 1ton-1do {保存每個葉節點的霍夫曼代碼和代碼的起始位}
開始
huff code【I】。bit【j】:= CD . bit【j】;
huff code【I】。start = cd.start
結束;
對於i:=0到n-1做{輸出每個葉節點的霍夫曼碼}
開始
for j:= huff code【I】。開始1到n-1做寫操作(huff code【I】)。bit【j】:10);
writeln
結束;
結束;