時間限制: 1 sec | 記憶體限制: 128 mb
輸入
輸入包含多組資料(不超過100組)
每組資料第一行乙個整數n,表示字元個數。接下來n行,每行有乙個字元ch和乙個整數weight,表示字元ch所對應的權值,中間用空格隔開。
輸入資料保證每組測試資料的字元不會重複。
輸出
對於每組測試資料,按照輸入順序輸出相應的字元以及它們的哈弗曼編碼結果,具體格式見樣例。
樣例輸入
3a 10
b 5c 8
4a 1
b 1c 1
d 1樣例輸出
a:0b:10
c:11
a:00
b:01
c:10
d:11
大致思路就是一次次的尋找最小權值結點構成乙個二叉樹,同時父結點將兩子結點的權值相加並插入,然後將父結點的權值插入到權值陣列裡,如此重複的 查詢結點、生成二叉樹、插入結點,直到陣列裡只剩下最後乙個結點,它就是這棵赫夫曼樹的根結點。
首先這裡有乙個權值陣列,將其存入到一棵樹的葉子結點裡
選出兩個權值最小的結點構成一棵簡單的二叉樹,父結點權值即為兩者之子結點之和
隨後將其父結點插入到結點陣列裡
再次選擇結點,構建二叉樹,插入結點, 重複操作,直到只剩下乙個結點。
如圖所示,最終結點就是這棵樹的根結點,赫夫曼樹構建完畢。
構建過程**如下
//構建哈夫曼樹
void
createhuffmantree
(huffmantree &
ht, int w[
], int n)
//非葉子結點的初始化
for(i = n +
1; i <= m; i++
)//建立非葉子結點即開始構建赫夫曼樹
for(i = n +
1; i <= m; i++
)}
完成了赫夫曼樹的構建,就要用它做點正事了,由此開始**赫夫曼編碼的生成。
首先了解一下什麼是赫弗曼編碼——其實就是字首碼的生成,只不過這裡要保證每乙個生成的字首碼都不是其他編碼的字首,這就可以引入上述**得出的赫夫曼樹了。
為什麼赫夫曼樹可以用來生成這樣的字首碼呢?
因為赫夫曼樹為每乙個權值分配了一條路徑,從根結點到某一權值結點的路徑上不會出現其他其他權值結點,其實也就是最初的權值結點都成為了最終赫夫曼樹的葉子結點。
赫夫曼樹中所有葉結點的帶權路徑長度之和——wpl,它的值是比較小的,這也就是它被稱作最優二叉樹的原因。
這一特性使其生成的編碼不會彼此間的字首,而且長度非常的短。
我們可以將左路徑設定為 0,右路徑設定為 1, 依次將每條路徑上的0,1編碼存入字元陣列裡;
在上圖中的赫夫曼樹,從根結點出發,一次向葉結點探索,如果要得到a的字首碼,路徑為右——右,因此它的編碼即為11。
再如 11 010 10 011 00 ,它的解碼即為 abcde。
這裡應題目要求,提供了乙個逆向生成的赫夫曼編碼
**段如下
//開始逆向生成赫夫曼編碼
void
creathuffmancode
(huffmantree &
ht, huffmancode *
hc, char *name, int n)
//為第i個編碼分配空間並儲存生成的編碼
hc[i]
=(char *
)malloc
((n - start)
*sizeof
(char));
strcpy(hc
[i],
&cd[start]);
}//釋放cd開始下一組編碼的生成
free
(cd)
;//列印編碼序列
for(i =
1; i <= n; i++
)printf
("%c:%s\n"
, name[i],hc
[i])
;}
不多噴了, 這道題題完整的ac**是這樣的
#include
#include
#include
//haffman 樹的結構
typedef struct
node,
*huffmantree;
//這裡選擇了動態分配陣列
typedef char *huffmancode;
//找出兩個最小權值結點並用指標帶回
void
select
(huffmantree ht
, int n, int *s1, int *s2)
}//繼續遍歷全部結點,找出權值最小的單節點
for(i =
1; i <= n; i++)}
}//找到了最小權值的結點,s1指向
*s1 = min;
//重複操作注意s1的干擾
for(i =
1; i <= n; i++)}
for(i =
1; i <= n; i++)}
}*s2 = min;
}//構建哈夫曼樹
void
createhuffmantree
(huffmantree &
ht, int w[
], int n)
//非葉子結點的初始化
for(i = n +
1; i <= m; i++
)//建立非葉子結點即開始構建赫夫曼樹
for(i = n +
1; i <= m; i++)}
//開始逆向生成赫夫曼編碼
void
creathuffmancode
(huffmantree &
ht, huffmancode *
hc, char *name, int n)
//為第i個編碼分配空間並儲存生成的編碼
hc[i]
=(char *
)malloc
((n - start)
*sizeof
(char));
strcpy(hc
[i],
&cd[start]);
}//釋放cd開始下一組編碼的生成
free
(cd)
;//列印編碼序列
for(i =
1; i <= n; i++
)printf
("%c:%s\n"
, name[i],hc
[i]);}
int main
(void
)createhuffmantree(ht
, w, n)
;creathuffmancode(ht
,&hc, name, n);}
return0;
}
首先、這篇部落格裡的些許內容借鑑了其他人的文章,畢竟資料結構的題目無論是設計,還是debug,都太費勁了, 我選擇了最優路徑。。。。。(流汗)
第二、
自從學習樹的第一講開始,就意識到以後的資料結構也會愈漸複雜,遇到的問題解決起來會越來越費勁,有些東西實現起來簡直是肝到爆,一次次的除錯更是弄得人心態**,但不管怎麼說——不能草草了事。
最後、
老規矩,ac了就趕緊睡覺, 頭髮最重要。。。。。。。
赫夫曼樹與赫夫曼編碼
問題描述 利用huffman編碼進行通訊可以大大提高通道利用率,縮短資訊傳輸時間,降低傳輸成本。但是,這要求在傳送端通過乙個編碼系統對待傳資料預先編碼,在接受端將傳來的資料編碼進行解碼 復原 對於有些通道,每端都需要乙個完整的編 解碼系統。試為這樣的資訊收發站編寫乙個huffman的編 解碼系統。給...
赫夫曼樹與赫夫曼編碼
赫夫曼樹又稱為最優二叉樹。帶權路徑長度wpl最小的二叉樹稱為最優二叉樹。從樹根結點到該結點之間的路徑長度與該結點上權的乘積稱為結點的帶權路徑長度,樹中所有葉子結點的帶權路徑長度之和稱為該樹的帶權路徑長度 wpl 通常記為 赫夫曼 huffman 樹的特徵 當葉子上的權值均相同時,完全二叉樹一定是最優...
赫夫曼樹和赫夫曼編碼
赫夫曼樹 1 先把有權值的葉子節點按照從小到大的順序排成乙個有序序列,即 a 5 e 10 b 15 d 30 c 40 2 取前兩個權值最小的結點即a 5 和e 10 作為乙個新的結點n1的兩個子節點,結點權值較小的作為左結點,即a為左結點,e為右結點,n1的權值為兩個結點權值的和,即5 10 1...