這一篇要總結的是樹中的最後一種,即哈夫曼樹,我想從以下幾點對其進行總結:
1,什麼是哈夫曼樹?
2,如何構建哈夫曼樹?
3,哈夫曼編碼?
4,演算法實現?
回到頂部
什麼是哈夫曼樹呢?
哈夫曼樹是一種帶權路徑長度最短的二叉樹,也稱為最優二叉樹。下面用一幅圖來說明。
它們的帶權路徑長度分別為:
圖a: wpl=5*2+7*2+2*2+13*2=54
圖b: wpl=5*3+2*3+7*2+13*1=48
可見,圖b的帶權路徑長度較小,我們可以證明圖b就是哈夫曼樹(也稱為最優二叉樹)。
回到頂部
一般可以按下面步驟構建:
1,將所有左,右子樹都為空的作為根節點。
2,在森林中選出兩棵根節點的權值最小的樹作為一棵新樹的左,右子樹,且置新樹的附加根節點的權值為其左,右子樹上根節點的權值之和。注意,左子樹的權值應小於右子樹的權值。
3,從森林中刪除這兩棵樹,同時把新樹加入到森林中。
4,重複2,3步驟,直到森林中只有一棵樹為止,此樹便是哈夫曼樹。
下面是構建哈夫曼樹的**過程:
三,哈夫曼編碼
利用哈夫曼樹求得的用於通訊的二進位制編碼稱為哈夫曼編碼。樹中從根到每個葉子節點都有一條路徑,對路徑上的各分支約定指向左子樹的分支表示」0」碼,指向右子樹的分支表示「1」碼,取每條路徑上的「0」或「1」的序列作為各個葉子節點對應的字元編碼,即是哈夫曼編碼。
就拿上圖例子來說:
a,b,c,d對應的哈夫曼編碼分別為:111,10,110,0
用圖說明如下:
記住,設計電文總長最短的二進位制字首編碼,就是以n個字元出現的頻率作為權構造一棵哈夫曼樹,由哈夫曼樹求得的編碼就是哈夫曼編碼。
摘自
在電報通訊中,電文是以二進位制的0、1序列傳送的。字符集中的字元的使用頻率是不同的(比如e和t的使用較之q和z要頻繁得多),哈夫曼編碼可以使得編碼的總長最短,從而相同的位長可以傳送更多的資訊。
本程式以下面的字元及使用頻率為例:
字元權值
a0.12
b0.40
c0.15
d0.08
e0.25
首先建立哈夫曼樹:i0
1234
5678
tree[i].chab
cde
tree[i].weight
0.12
0.40
0.15
0.08
0.25
0.20
0.35
0.60
1.00
tree[i].parent58
6576
780tree[i].lchild
-1-1
-1-1-13
241tree[i].rchild
-1-1
-1-1-10
567
得到哈夫曼樹和哈夫曼編碼如下:
下面是哈夫曼編碼的儲存結構:
序號bits
chstart01
111a
21
0b52 11
0c33
1110
d24
10e4
程式清單如下:
#include
#define n 5 //葉子數目
#define m (2*n-1)
//結點總數
#define maxval 10000.0
#define maxsize 100
//哈夫曼編碼的最大位數
typedef struct
hufmtree;
typedef struct
codetype;
void huffman(hufmtree tree);//建立哈夫曼樹
void huffmancode(codetype code,hufmtree tree);//根據哈夫曼樹求出哈夫曼編碼
void decode(hufmtree tree);//依次讀入電文,根據哈夫曼樹解碼
void main()
printf("【讀入電文,並進行解碼】\n");
decode(tree);//依次讀入電文,根據哈夫曼樹解碼
}void huffman(hufmtree tree)//建立哈夫曼樹
printf("【依次讀入前%d個結點的字元及權值(中間用空格隔開)】\n",n);
for(i=0;i //讀入前n個結點的字元及權值
for(i=n;i
//進行n-1次合併,產生n-1個新結點
else
if(tree[j].weight
tree[p1].parent=i;
tree[p2].parent=i;
tree[i].lchild=p1; //最小權根結點是新結點的左孩子
tree[i].rchild=p2; //次小權根結點是新結點的右孩子
tree[i].weight=tree[p1].weight+tree[p2].weight;
}}//huffman
void huffmancode(codetype code,hufmtree tree)//根據哈夫曼樹求出哈夫曼編碼
//codetype code為求出的哈夫曼編碼
//hufmtree tree為已知的哈夫曼樹
code[i]=cd;
//第i+1個字元的編碼存入code[i]
}}//huffmancode
void decode(hufmtree tree)//依次讀入電文,根據哈夫曼樹解碼
j++;
}printf("\n");
if(tree[i].lchild!=-1&&b[j]!='2')
//電文讀完,但尚未到葉子結點
printf("\nerror\n"); //輸入電文有錯
}//decode
貼出一例執行結果:
摘自
哈夫曼樹編 解碼演算法
一 實驗目的 掌握哈弗曼編 解碼演算法。1.掌握huffman 樹的概念 特點和儲存結構 2.掌握huffman 樹的構造方法 3.學會靈活運用huffman 樹解決編碼問題。4.問題描述 5.某報文中共出現n個字元,各字元出現頻度依次為w1,w2,wn。要求設計乙個不等長的編碼方案,輸出每個字元對...
哈夫曼樹建立和解碼
題目描述 假設某通訊報文的字符集由a,b,c,d,e,f這6個字元組成,它們在報文 現的頻度 頻度均為整數值 1 構造一棵哈弗曼樹,依次給出各字元編碼結果。2 給字串進行編碼。3 給編碼串進行解碼。規定 構建哈弗曼樹時 左子樹根結點權值小於等於右子樹根結點權值。生成編碼時 左分支標0,右分支標1。輸...
哈夫曼樹的建立以及哈夫曼編碼
主要源 如下 include include define max num 105 typedef struct htnode,htree void selecttwomin htree ht,int n,int s1,int s2 ht s1 visited 1 將最小的頻率對應的結點標記為已被訪...