1. 程式人生 > >哈夫曼樹+哈夫曼編碼

哈夫曼樹+哈夫曼編碼

http 結合 nbsp 情況 帶權路徑 ast 二叉樹 葉子 介紹

前天acm實驗課,老師教了幾種排序,抓的一套題上有一個哈夫曼樹的題,正好之前離散數學也講過哈夫曼樹,這裏我就結合課本,寫一篇關於哈夫曼樹的博客。

哈夫曼樹的介紹

Huffman Tree,中文名是哈夫曼樹或霍夫曼樹,它是最優二叉樹。

定義:給定n個權值作為n個葉子結點,構造一棵二叉樹,若樹的帶權路徑長度達到最小,則這棵樹被稱為哈夫曼樹。 這個定義裏面涉及到了幾個陌生的概念,下面就是一顆哈夫曼樹,我們來看圖解答。

技術分享圖片

(01) 路徑和路徑長度

定義:在一棵樹中,從一個結點往下可以達到的孩子或孫子結點之間的通路,稱為路徑。通路中分支的數目稱為路徑長度。若規定根結點的層數為1,則從根結點到第L層結點的路徑長度為L-1。 例子

:100和80的路徑長度是1,50和30的路徑長度是2,20和10的路徑長度是3。

(02) 結點的權及帶權路徑長度

定義:若將樹中結點賦給一個有著某種含義的數值,則這個數值稱為該結點的權。結點的帶權路徑長度為:從根結點到該結點之間的路徑長度與該結點的權的乘積。 例子:節點20的路徑長度是3,它的帶權路徑長度= 路徑長度 * 權 = 3 * 20 = 60。

(03) 樹的帶權路徑長度

定義:樹的帶權路徑長度規定為所有葉子結點的帶權路徑長度之和,記為WPL。 例子:示例中,樹的WPL= 1*100 + 2*80 + 3*20 + 3*10 = 100 + 160 + 60 + 30 = 350。

比較下面兩棵樹

技術分享圖片

上面的兩棵樹都是以{10, 20, 50, 100}為葉子節點的樹。

左邊的樹WPL=2*10 + 2*20 + 2*50 + 2*100 = 360 右邊的樹WPL=350

左邊的樹WPL > 右邊的樹的WPL。你也可以計算除上面兩種示例之外的情況,但實際上右邊的樹就是{10,20,50,100}對應的哈夫曼樹。至此,應該堆哈夫曼樹的概念有了一定的了解了,下面看看如何去構造一棵哈夫曼樹。

哈夫曼樹的圖文解析

假設有n個權值,則構造出的哈夫曼樹有n個葉子結點。 n個權值分別設為 w1、w2、…、wn,哈夫曼樹的構造規則為:

1. 將w1、w2、…,wn看成是有n 棵樹的森林(每棵樹僅有一個結點); 2

. 在森林中選出根結點的權值最小的兩棵樹進行合並,作為一棵新樹的左、右子樹,且新樹的根結點權值為其左、右子樹根結點權值之和; 3. 從森林中刪除選取的兩棵樹,並將新樹加入森林; 4. 重復(02)、(03)步,直到森林中只剩一棵樹為止,該樹即為所求得的哈夫曼樹。

以{5,6,7,8,15}為例,來構造一棵哈夫曼樹。

技術分享圖片

第1步:創建森林,森林包括5棵樹,這5棵樹的權值分別是5,6,7,8,15。 第2步:在森林中,選擇根節點權值最小的兩棵樹(5和6)來進行合並,將它們作為一顆新樹的左右孩子(誰左誰右無關緊要,這裏,我們選擇較小的作為左孩子),並且新樹的權值是左右孩子的權值之和。即,新樹的權值是11。 然後,將"樹5"和"樹6"從森林中刪除,並將新的樹(樹11)添加到森林中。 第3步:在森林中,選擇根節點權值最小的兩棵樹(7和8)來進行合並。得到的新樹的權值是15。 然後,將"樹7"和"樹8"從森林中刪除,並將新的樹(樹15)添加到森林中。 第4步:在森林中,選擇根節點權值最小的兩棵樹(11和15)來進行合並。得到的新樹的權值是26。 然後,將"樹11"和"樹15"從森林中刪除,並將新的樹(樹26)添加到森林中。 第5步:在森林中,選擇根節點權值最小的兩棵樹(15和26)來進行合並。得到的新樹的權值是41。 然後,將"樹15"和"樹26"從森林中刪除,並將新的樹(樹41)添加到森林中。 此時,森林中只有一棵樹(樹41)。這棵樹就是我們需要的哈夫曼樹!

哈夫曼樹+哈夫曼編碼