版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
最優(yōu)二叉樹樹的帶權(quán)路徑長度定義為:WPL(T):樹T中所有葉子結(jié)點的帶權(quán)路徑長度之和ABCHIDEFG5249WPL(T)=7×2+5×2+2×3+4×3+9×2=607最優(yōu)二叉樹ABHDGCIFE74952WPL(T)=7×4+9×4+5×3+4×2+2×1=89最優(yōu)二叉樹最優(yōu)二叉樹定義為:帶權(quán)路徑長度WPL最小的二叉樹,又稱為哈夫曼樹。哈夫曼樹例如:已知權(quán)值W={5,6,2,9,7}9562769692571)2)3)2577713哈夫曼樹WPL=2×3+5×3+6×2+7×2+9×2=6562574)5)137162992571696713練習(xí):已知權(quán)值W={5,6,2,9,8}哈夫曼樹95628686521)2)3)529897713哈夫曼樹4)5)WPL=2×3+5×3+6×2+8×2+9×2=672521317771713308965689哈夫曼樹(哈夫曼算法)以二叉樹為例:1.根據(jù)給定的n個權(quán)值{w=w1,w2,…,wn},構(gòu)造n棵二叉樹的集合F={T1,T2,…,Tn},其中每棵二叉樹中均只含一個帶權(quán)值為wi的根結(jié)點,其左、右子樹為空樹;2.在F中選取其根結(jié)點的權(quán)值為最小的兩棵二叉樹,分別作為左、右子樹構(gòu)造一棵新的二叉樹,并置這棵新的二叉樹根結(jié)點的權(quán)值為其左、右子樹根結(jié)點的權(quán)值之和;3.從F中刪去這兩棵樹,同時將剛生成的新樹加入到F中;4.重復(fù)(2)和(3)兩步,直至F中只含一棵樹為止。哈夫曼樹特點:1、有n個葉子結(jié)點:過程中的第1步2、沒有度為1的結(jié)點:2個節(jié)點作為左右孩子生成1個新的節(jié)點3、總的結(jié)點數(shù)為2n-1:需要合并n-1次,每次增加1個節(jié)點4、深度≤n-15、形態(tài)不唯一編碼編碼:用二進制數(shù)表示字符等例如:ASCII碼,擴展的ASCII碼特點:等長編碼定長編碼假設(shè)有8個符號:a0 a1 a2 a3 a4 a5 a6 a7000 001 010 011 100 101 110 111011110000100001???變長編碼有時候,每個字符出現(xiàn)的頻率不一樣,采用變長編碼,使得出現(xiàn)頻率高的編碼短,頻率低的編碼長,使得整體的編碼短。假設(shè)A0.4B0.3C0.2D0.1A B C D0 1 00 010001011???任何一個字符的編碼都不是同一字符集中另一個字符的編碼的前綴。利用哈夫曼樹可以構(gòu)造一種不等長的二進制編碼,并且構(gòu)造所得的哈夫曼編碼是一種最優(yōu)前綴編碼,即:所傳電文的總長度最短。Prefix-freecode(前綴編碼)010100110001100101111、建立哈夫曼樹2、對邊編號3、求出葉子結(jié)點的路徑4、得到字符編碼A B C D E6 7 2 5 900 01 100 101 11291367167925Prefix-freecode(前綴編碼)如何譯碼?001011110001???ADECB01010011291367167925A B C D E6 7 2 5 900 01 100 101 11Prefix-freecode(前綴編碼)Huffman樹的實現(xiàn)
private
static
classNode{
char
data;//葉子結(jié)點放待編碼的符號 Nodeleft; Noderight; Node(char
data,Nodeleft,Noderight){ this.data=data; this.left=left;
this.right=right; } }Huffman樹的實現(xiàn)
privateNoderoot;//根結(jié)點
private
float
weight;//樹中葉子結(jié)點的權(quán)重之和
privateMap<Character,Byte[]>coder;//存放<符號,編碼>,可以考慮使用BitSet替換Byte[]
private
static
byte
LEFT=0;//左子樹
private
static
byte
RIGHT=1;//右子樹
public
intcompareTo(HuffmanTreerhd){//為了使用優(yōu)先隊列,需要比較大小,值小的獲勝
returnFpare(this.weight,rhd.weight); }合并Huffman樹
static
privateHuffmanTreemerge(HuffmanTreelhd,HuffmanTreerhd){//合并2棵哈夫曼樹 HuffmanTreeresult=newHuffmanTree();
result.root=newNode('\0',lhd.root,rhd.root);//中間結(jié)點,\0可以替換成任意的符號
result.weight=lhd.weight+rhd.weight;
lhd.root=rhd.root=null;
lhd.weight=rhd.weight=0;
return
result; }
privateHuffmanTree(){//空樹 }
privateHuffmanTree(char
symbol,float
weight){//只有根結(jié)點的樹
this.weight=weight;
root=newNode(symbol,null,null); }建立Huffman樹
static
publicHuffmanTreemakeTree(char[]symbol,float[]weights){
if(weights.length!=symbol.length||weights.length<2)
throw
newIllegalStateException(); PriorityQueue<HuffmanTree>pq=newPriorityQueue<>(weights.length);
for(int
i=0;i<weights.length;i++)//創(chuàng)建葉子結(jié)點對應(yīng)的霍夫曼樹,并入隊
pq.offer(newHuffmanTree(symbol[i],weights[i]));
while(pq.size()!=1){//取2棵最小的樹,合并后得到1棵新樹,再放入隊列
pq.offer(merge(pq.poll(),pq.poll())); }
return
pq.poll(); }Huffman編碼-譯碼//只能處理1個符號使用了1個char場合public
classHuffmanCoding{
privateHuffmanTreeht;
privateMap<Character,Byte[]>coder;//符號編碼表,存放<符號,編碼>
private
static
byte
LEFT=0;//左子樹的標識
private
static
byte
RIGHT=1;//右子樹的標識
publicHuffmanCoding(HuffmanTreeht){
this.ht=ht; }獲取編碼表
private
voidmakeCodeList(){//根據(jù)霍夫曼樹建立符號編碼表
coder=newHashMap<>(); Deque<Byte>stack=newArrayDeque<>(); preCoding(ht.root.left,LEFT,stack); preCoding(ht.root.right,RIGHT,stack); }獲取編碼表
private
voidpreCoding(Nodet,byte
b,Deque<Byte>stack){
//為了toArray的次序和從根到葉子結(jié)點的路徑的次序一致,使用Deque的右端棧
stack.addLast(b);
if(t.left==null&&t.right==null){//葉子結(jié)點 Byte[]code=newByte[stack.size()];
stack.toArray(code);
coder.put(t.data,code); }else{ preCoding(t.left,LEFT,stack); preCoding(t.right,RIGHT,stack); }
stack.removeLast();//回溯 }01000100110110010111291367167925編碼
publicByte[]enCoder(Stringstr){
if(coder==null)//第1次使用這棵哈夫曼樹編碼 makeCodeList();
int
len=str.length(); List<Byte[]>list=newArrayList<>(len);//存放各字符的編碼
int
count=0;//編碼的總長度
for(int
i=0;i<len;i++){ Byte[]b=coder.get(str.charAt(i));//查表,獲取字符的編碼
count+=b.length;
list.add(b); } Byte[]result=newByte[count];//str的編碼
int
pos=0;
for(int
i=0;i<list.size();i++){ Byte[]b=list.get(i); System.arraycopy(b,0,result,pos,b.length);
pos+=b.length; }
return
result; }譯碼
publicStringdeCoder(Byte[]code){//沒有處理一些特殊情況 StringBuilderresult=newStringBuilder(); Nodenode=ht.root;
for(int
i=0;i<code.length;i++){
if(code[i].byteValue()==LEFT)
node=node.left;
else
node=node.right;
if(node.left==null&&node.right==null){//葉子結(jié)點
result.append(node.data);//葉子結(jié)點中存的符號
node=ht.root;//譯出一個字符后,再從根開始 } }
return
result.toString(); }測試10010111111111010110010101000111011helloworld
public
static
voidmain(String[]args){
float[]weights={9f,7f,5f,4f,2f};
char[]symbol={'A','B','C','D','E'}; HuffmanCodinghc=newHuffmanCoding(HuffmanTree.makeTree(symbol,weights)); Stringstr="ABECD"; Byte[]codes=hc.enCoder(str);
for(int
i=0;i<codes.length;i++) System.out.print(codes[i]); System.out.println(); System.out.println(hc.deCoder(codes)); }總結(jié)1、哈夫曼樹提供了對符號集的一種前綴編碼,用于文本壓縮、通訊等。2、哈夫曼樹算法比較簡單,在實現(xiàn)時用到了Map、PriorityQueue等數(shù)據(jù)結(jié)構(gòu)。很好的說明了算法和數(shù)據(jù)結(jié)構(gòu)的關(guān)系。3、代碼沒有考慮各種特殊情形,而且簡單的用Byte保存編碼,可以考慮用BitSet等替換,或進一步處理成其它形式。處理雙char的符號
public
static
voidmain(String[]args){
float[]weights={0.01f,0.01f,0.01f,0.20f,0.3f,0.2f,0.1f,0.2f}; String[]symbol={"??","??","??","漢","字","1","2","3"}; HuffmanTree1ht=newHuffmanTree1(symbol,weights); Stringstr="??????漢字123"; Byte[]codes=ht.coding(str);
for(int
i=0;i<codes.length;i++) System.out.print(codes[i]); System.out.println(); System.out.println(ht.decoding(codes)); }??這樣的符號不能用1個char,而是2個char,可以使用String處理雙char的符號
private
static
classNode{
Stringdata; Nodeleft; Noderight; Node(Stringdata,Nodeleft,Noderight){
this.data=data;
this.left=left;
this.right=right; } }處理雙char的符號
publicByte[]enCoder(Stringstr){//該方法變了
if(coder==null)//第1次編碼 makeCodeList(); List<Byte[]>list=newArrayList<>();
int
count=0;//編碼的總長度
int
i=0;
while(i<str.length()){ Byte[]b;
//1個符號需要2個char,高位的char是HighSurrogate
if(Character.isHighSurrogate(str.charAt(i))){
b=coder.get(str.substring(i,i+2));
i+=2; }else{
b=coder.get(str.substring(i,i+1)); ++i; }
count+=b.length;
list.add(b); }
//各個字符的總編碼 Byte[]result=newByte[count];
int
pos=0;
for(int
j=0;j<list.size();j++){ Byte[]b=list.get(j); System.arraycopy(b,0,result,pos,b.length);
pos+=b.length; }
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 比粗細課件教學(xué)課件
- 2024健身房與會員之間的會員服務(wù)合同
- 2024年建筑工人勞務(wù)雇傭協(xié)議
- 2024年度藝人非獨家合作合同及演出安排
- 2024年廣告發(fā)布與媒體推廣合同
- 2024年度廢舊物資回收利用合同的履行
- 2024年度技術(shù)研發(fā)計算機軟件開發(fā)合同
- 制作高端課件教學(xué)課件
- 04年數(shù)據(jù)中心運維服務(wù)合同
- 2024年廢棄物處理服務(wù)合同(含危險廢物)
- 妊娠期高血壓護理查房醫(yī)學(xué)課件
- 新部編人教版四年級上冊語文課件(第16課 風(fēng)箏)
- 臨床診斷與思維步驟課件
- 放射科危急值制度考試試題與答案
- 通信發(fā)展的前世今生兒童科普(課堂PPT)課件(PPT 38頁)
- 老年人口腔保健知識PPT課件
- 荒蕪?fù)恋鼗謴?fù)與重建的生態(tài)工程匯總
- 怎么才能快速學(xué)會做賬
- 第四章齲病的預(yù)防
- 內(nèi)鏡中心進修護士培訓(xùn)計劃
- 深圳市不動產(chǎn)登記申請表
評論
0/150
提交評論