哈夫曼編碼簡介

2021-08-27 16:30:27 字數 2706 閱讀 4696

哈弗曼編碼幾乎是所有壓縮演算法的基礎,其實這個演算法並不複雜,簡單的理解就是,如何用更短的bit來編碼資料。

我們知道普通的編碼都是定長的,比如常用的ascii編碼,每個字元都是8個bit:

這樣,計算機就能很方便的把由0和1組成的資料流解析成原始資訊,但我們知道,在很多情況下,資料檔案中的字元出現的概率是不均勻的,比如在一篇英語文章中,字母「e」出現的頻率最高,「z」最低,如果我們使用不定長的bit編碼,頻率高的字母用比較短的編碼表示,頻率低的字母用長的編碼表示,豈不是可以大大縮小檔案的空間嗎?

但這就要求編碼要符合「字首編碼」的要求,即較短的編碼不能是任何較長的編碼的字首,這樣解析的時候才不會混淆,比如下面的編碼方法就符合字首原則:

根據這個碼表,下面一段資料就可以唯一解析成原始資訊了:

1110010101110110111100010 – dabbdceaab

要生成這種編碼,最方便的就是用二叉樹,考察一下下面這個樹

把要編碼的字元放在二叉樹的葉子上,所有的左節點是0,右節點是1,從根瀏覽到葉子上,因為字元只能出現在樹葉上,任何乙個字元的路徑都不會是另一字元路徑的字首路徑,符合字首原則編碼就可以得到

現在我們可以開始考慮壓縮的問題,如果有一篇只包含這五個字元的文章,而這幾個字元的出現的次數如下:

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

可以看出,構造更優的二叉樹,原則就是權重越大的葉子,距離根應該越近,而我們的終級目標是生成「最優」的二叉樹,最優二叉樹必須符合下面兩個條件:

1.所有上層節點都大於等於下層節點。

2.某節點,設其較大的子節點為m,較小的子節點為n,m下的任一層的所有節點都應大於等於n下的該層的所有節點。

上面這個例子是比較簡單的,實際的檔案中,乙個位元組有256種可能的取值,所以二叉樹的葉子節點多達256個,最終的樹形可能非常複雜,但有一種非常精巧的演算法可以快速地建起一棵最優二叉樹,這種演算法由d.huffman(戴?哈夫曼)提出,下面我們先來介紹哈弗曼演算法的步驟,然後再來證明通過這麼簡單的步驟得出的樹形確實是一棵最優二叉樹。

哈夫曼演算法的步驟是這樣的:

比如上面的例子,哈弗曼樹建立的過程如下:

1)列出原始的節點資料:

2)將最小的兩個節點c和e結合起來:

3)再將新的節點和a組合起來

4)再將d節點加入

5)如此迴圈,最終得到乙個最優二叉樹

生成的資料檔案長度為:

3*6 + 1*15 + 4*2 + 2*9 + 4*1 = 63

下面我們用逆推法來證明對於各種不同的節點序列,用哈弗曼演算法建立起來的樹總是一棵最優二叉樹:

當這個過程中的節點序列只有兩個節點時(比如前例中的15和18),肯定是一棵最優二叉樹,乙個編碼為0,另乙個編碼為1,無法再進一步優化。

然後往前步進,節點序列中不斷地減少乙個節點,增加兩個節點,在步進過程中將始終保持是一棵最優二叉樹,這是因為:

按照哈弗曼樹的建立過程,新增的兩個節點是當前節點序列中最小的兩個,其他的任何兩個節點的父節點都大於(或等於)這兩個節點的父節點,只要前一步是最優二叉樹,其他的任何兩個節點的父節點就一定都處在它們的父節點的上層或同層,所以這兩個節點一定處在當前二叉樹的最低一層。

這兩個新增的節點是最小的,所以無法和其他上層節點對換。符合我們前面說的最優二叉樹的第乙個條件。

只要前一步是最優二叉樹,由於這兩個新增的節點是最小的,即使同層有其他節點,也無法和同層其他節點重新結合,產生比它們的父節點更小的上層節點來和同層的其他節點對換。它們的父節點小於其他節點的父節點,它們又小於其他所有節點,只要前一步符合最優二叉樹的第二個條件,到這一步仍將符合。

這樣一步步逆推下去,在這個過程中哈弗曼樹每一步都始終保持著是一棵最優二叉樹。

哈夫曼編碼簡介

我們知道普通的編碼都是定長的,比如常用的ascii編碼,每個字元都是8個bit 字元編碼 a00101001 b00101010 c00101011 這樣,計算機就能很方便的把由0和1組成的資料流解析成原始資訊,但我們知道,在很多情況下,資料檔案中的字元出現的概率是不均勻的,比如在一篇英語文章中,字...

哈夫曼編碼簡介

哈弗曼編碼幾乎是所有壓縮演算法的基礎,其實這個演算法並不複雜,簡單的理解就是,如何用更短的bit來編碼資料。我們知道普通的編碼都是定長的,比如常用的ascii編碼,每個字元都是8個bit 字元 編碼 a00101001 b00101010 c00101011 這樣,計算機就能很方便的把由0和1組成的...

哈夫曼編碼 哈夫曼樹

1.定義 哈夫曼編碼主要用於資料壓縮。哈夫曼編碼是一種可變長編碼。該編碼將出現頻率高的字元,使用短編碼 將出現頻率低的字元,使用長編碼。變長編碼的主要問題是,必須實現非字首編碼,即在乙個字符集中,任何乙個字元的編碼都不是另乙個字元編碼的字首。如 0 10就是非字首編碼,而0 01不是非字首編碼。2....