哈弗曼編碼幾乎是所有壓縮演算法的基礎,其實這個演算法並不複雜,簡單的理解就是,如何用更短的bit來編碼資料。
我們知道普通的編碼都是定長的,比如常用的ascii編碼,每個字元都是8個bit:
字元
編碼
a00101001
b00101010
c00101011……
這樣,計算機就能很方便的把由0和1組成的資料流解析成原始資訊,但我們知道,在很多情況下,資料檔案中的字元出現的概率是不均勻的,比如在一篇英語文章中,字母「e」出現的頻率最高,「z」最低,如果我們使用不定長的bit編碼,頻率高的字母用比較短的編碼表示,頻率低的字母用長的編碼表示,豈不是可以大大縮小檔案的空間嗎?
但這就要求編碼要符合「字首編碼」的要求,即較短的編碼不能是任何較長的編碼的字首,這樣解析的時候才不會混淆,比如下面的編碼方法就符合字首原則:
字元
編碼a0
b10c110
d1110
e11110……
根據這個碼表,下面一段資料就可以唯一解析成原始資訊了:
1110010101110110111100010 – dabbdceaab
要生成這種編碼,最方便的就是用二叉樹,考察一下下面這個樹
把要編碼的字元放在二叉樹的葉子上,所有的左節點是0,右節點是1,從根瀏覽到葉子上,因為字元只能出現在樹葉上,任何乙個字元的路徑都不會是另一字元路徑的字首路徑,符合字首原則編碼就可以得到
字元
編碼a00
b010
c011d10
e11現在我們可以開始考慮壓縮的問題,如果有一篇只包含這五個字元的文章,而這幾個字元的出現的次數如下:
a: 6次
b : 15次
c: 2次
d : 9次
e: 1次
用過用定長的編碼,每個字元3bit,這篇文章總長度為:
3*6 + 3*15 + 3*2 + 3*9 + 3*1 = 99
而用上面用二叉樹生成的編碼,總長度為:
2*6 + 3*15 + 2*2 + 2*9 + 2*1 = 80
顯然,這顆樹還可以進一步優化,使得編碼更短,比如下面的編碼
生成的資料長度為:
3*6 + 1*15 + 4*2 + 2*9 + 4*1 = 63
可以看出,構造更優的二叉樹,原則就是權重越大的葉子,距離根應該越近,而我們的終級目標是生成「最優」的二叉樹,最優二叉樹必須符合下面兩個條件:
所有上層節點都大於等於下層節點。
某節點,設其較大的子節點為m,較小的子節點為n,m下的任一層的所有節點都應大於等於n下的該層的所有節點。
上面這個例子是比較簡單的,實際的檔案中,乙個位元組有256種可能的取值,所以二叉樹的葉子節點多達256個,最終的樹形可能非常複雜,但有一種非常精巧的演算法可以快速地建起一棵最優二叉樹,這種演算法由d.huffman(戴?哈夫曼)提出,下面我們先來介紹哈弗曼演算法的步驟,然後再來證明通過這麼簡單的步驟得出的樹形確實是一棵最優二叉樹。
哈夫曼演算法的步驟是這樣的:
這樣一步步逆推下去,在這個過程中哈弗曼樹每一步都始終保持著是一棵最優二叉樹。
哈弗曼編碼 哈弗曼樹
哈弗曼編碼是依賴於字元使用頻率來建立的一種編碼,通過把使用頻率低的字元分配相對較多的01編碼,而使用頻率高的分配相對較低的01編碼,來建立最小的帶權路徑長度的樹,來最大化的獲得編碼儲存空間的一種編碼規則。這個樹稱為哈弗曼樹,也稱為最優二叉樹。這樣可以確定每乙個字元的編碼不可能成為其他字元編碼的坐子串...
哈弗曼樹與哈弗曼編碼(實現)
歷史背景 1951年,霍夫曼在mit攻讀博士學位,他和修讀資訊理論課程的同學得選擇是完成學期報告還是期末考試。導師robert fano出的學期報告題目是 查詢最有效的二進位制編碼。由於無法證明哪個已有編碼是最有效的,霍夫曼放棄對已有編碼的研究,轉向新的探索,最終發現了基於有序頻率二叉樹編碼的想法,...
哈弗曼編碼
include include include define my strmax 100 define infinity 1000000 typedef struct htnode,huffmantree 動態分配陣列儲存赫夫曼樹 typedef char huffmancode 動態分配陣列儲存赫...