演算法導論之哈夫曼編碼

2021-07-10 05:15:22 字數 2870 閱讀 4285

今天和大家一起討論haffman編碼,哈夫曼編碼是基於哈夫曼樹,也可以被稱為最有二叉樹,哈夫曼編碼可以有效的壓縮資料,通常可以節省20%~90%,具體的壓縮率依賴於資料的特性。首先給大家介紹一下什麼是最優二叉樹;在介紹什麼是最有二叉樹之前,先說明兩個概念 ,

i>葉子節點的路徑長度:從根到葉子節點的邊的個數;

ii>葉子節點的帶權路徑長度(wpl):葉子節點的權值 * 路徑長度;

(1) 最優二叉樹(haffman tree):一顆二叉樹的所有葉子節點的帶權路徑長度之和最小。

例:有節點 a(9)、b(2)、c(7)、d(4)

第一種構建二叉樹的方式: x

/     \

x       x

/    \     /    \

a    b   c    d

其wpl值為:(9 + 2+ 7 + 4)* 2 = 44

第二種構建二叉樹的方式:x

/     \

a       x

/    \

c    x

/   \

b   d

將權值大放在靠近根結點的位置;其wpl值為:9 + 7 * 2 + (2 + 4)*3 = 41

(2)構造哈夫曼樹 ------->貪心演算法

i>  初始 :森林:f =

ii>處理:從森林中選取權值最小和次小的2顆樹構建成一顆新二叉樹,並放回森林,並刪除原來的2顆二叉樹

iii>重複ii>,直至森林中只剩一顆二叉樹。

例:f = 

i>           6

/     \

b     d          --->       放回森林,並刪除b、d兩顆二叉樹

(2)    (4) 

ii>                        13

/    \

6     c(7)           --->放回森林,並刪除6、c兩顆二叉樹

/   \

b  d    

(2)  (4)

iii>                           22

/    \

a     13

(9)       /   \

6    c(7)

/   \

b    d

(2)  (4)

在構造二叉樹時會遇到以下的幾個問題:

a>如何查詢權值最小和次小的兩顆子樹:-------貪心準則

b>如何構建一顆新的子樹:

i>建立雙親 ----權值為左右子樹之和

ii>左子女 --->最小      右子女 --->次小

c>如何知道森林中只剩下一顆子樹 -------->結束條件

i>haffman樹無單分支節點

ii>經過n - 1次就可構建完成

實現haffman tree

1)儲存結構:

word       weight      left      right     parent      code

a              9            -1         -1           -1

b              2            -1         -1           -1 

c              7            -1         -1           -1

d              4            -1         -1           -1

定義儲存結構:

下面實現介面:

#include #include #include "hafman.h"

#include "tools.h"

hafftree *init(char * s,int * a,int n)

; int i = 0;

f = (hafftree *)malloc(((2 * n) - 1) * sizeof(hafftree));

for(i = 0;i < n;i++)

return f;

}void creat_haffmantree(hafftree *f,int n)

else if(f[j].weight < f[k2].weight)}}

f[n + i].word = 'x';

f[n + i].weight = f[k1].weight + f[k2].weight;

f[n + i].left = k1;

f[n + i].right = k2;

f[n + i].parent = -1;

f[k1].parent = n + i;

f[k2].parent = n + i;

}}void haffman_code(hafftree *f,int n)

else

c = p;}}

}void print_haffmancode(hafftree *f,int n)

printf("\n");

}}void clearhaffman(hafftree *f,int n)

free(f);

}

測試**:

測試結果:

從程式執行結果上可看出實現了壓縮資料,節省了空間。

演算法 哈夫曼編碼

計算機中使用二進位制編碼字元 哈夫曼編碼是通過構造哈夫曼樹得到的,哈夫曼樹是通過貪心演算法得到的 貪心演算法構造哈夫曼樹 將字元出現的次數作為哈夫曼樹的權值,按照貪心演算法,選擇權值最小的兩個結點,成為乙個數的左右結點 左右子結點的權值變為子樹根的權值 然後在餘下的結點中遞迴選用最小的兩個結點 根據...

哈夫曼編碼 哈夫曼樹

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

哈夫曼樹 哈夫曼編碼

定義從a結點到b結點所經過的分支序列為從a結點到b結點的路徑 定義從a結點到b結點所進過的分支個數為從a結點到b結點的路徑長度 從二叉樹的根結點到二叉樹中所有結點的路徑長度紙盒為該二叉樹的路徑長度 huffman樹 帶權值路徑長度最小的擴充二叉樹應是權值大的外界點舉例根結點最近的擴充二叉樹,該樹即為...