赫夫曼樹和赫夫曼編碼

2021-10-07 12:42:37 字數 3184 閱讀 6416

以下內容主要參考了嚴蔚敏版的資料結構教材。

赫夫曼樹又叫做最優樹,是一類帶權路徑長度最短的樹,這裡討論的是最優二叉樹。

假設現在有n個權值w1,

w2,.

..,w

nw_1,w_2,...,w_n

w1​,w2

​,..

.,wn

​,如何構造一顆有n個葉子節點的二叉樹使得二叉樹的帶權路徑長度(∑k=

1nwk

∗lk\sum_^n w_k*l_k

∑k=1n​

wk​∗

lk​)最小,其中w1,

w2,.

..,w

nw_1,w_2,...,w_n

w1​,w2

​,..

.,wn

​分別是n個葉子節點的權值l1,

l2,.

..,l

nl_1,l_2,...,l_n

l1​,l2

​,..

.,ln

​分別是n個葉子節點的路徑長度(即樹根到該節點的分支數目)。這樣額的二叉樹叫做最優二叉樹或赫夫曼樹。

構造赫夫曼樹的演算法如下:

根據給定的n個權值w1,

w2,.

..,w

nw_1,w_2,...,w_n

w1​,w2

​,..

.,wn

​構成n顆二叉樹的集合f

=f=\

f=,此時每棵二叉樹都只有乙個權值為w

iw_i

wi​的根節點,左右子樹均為空。

在集合f中選取兩顆根節點的權值最小的二叉樹作為左右子樹構建一顆新的二叉樹,新的二叉樹的根節點的權值為左右兩顆子樹的根節點權值的和。

在集合f中刪除這兩顆二叉樹同時將新建立的二叉樹加入到集合f中。

重複步驟2和3直到f中只有一顆二叉樹時為止。此時即為所求。

圖1是乙個簡單的例子,測試程式也是在該例子上進行測試的。

最優二叉樹的乙個應用是設計二進位制字首編碼。字首編碼是一種不等長的編碼,對於每個要編碼的字元其對應的編碼長度不同且每乙個字元的編碼都不是另乙個字元對應的編碼的字首。這樣便於解碼。可以將出現頻率較高的字元編碼較少的位數,將出現頻率較低的字元編碼較多的位數,這樣可以使得整體要傳送的資料減少,提高了效率。用最優二叉樹來設計二進位制字首編碼比較簡單,將字元出現的頻率當做權重,來構建相應的最優二叉樹,然後將二叉樹左分支的邊設為編碼』0』,右分支的邊設為編碼』1』。之後再從根節點到相應葉子節點的字串就是葉子節點對應的字元的二進位制字首編碼。

class

huffmannode

void

setweight

(int value)

void

setparent

(int value)

void

setleftchild

(int value)

void

setrightchild

(int value)

intgetweight()

intgetparent()

intgetleftchild()

intgetrightchild()

};class

huffmantree

elseif(

(nodes[i]

.getparent()

==0)&&

(countparentzero ==1)

)}elseif(

(nodes[i]

.getparent()

==0)&&

(countparentzero >1)

)elseif(

(nodes[temps1]

.getweight()

< nodes[i]

.getweight()

)&&(nodes[i]

.getweight()

<= nodes[temps2]

.getweight()

))countparentzero++;}

} s1=temps1;

s2=temps2;

return;}

public

:huffmantree

(int leafnodenum,vector<

int> leafnodeweight)

}void

printcodingup()

}void

printcodingdown()

}void

printtree()

}void

constructtree()

}//從葉子節點開始求每個字元的huffman編碼

void

huffmancodingup()

else

}//因為是從葉子節點開始求每個字元的huffman編碼,求得編碼後需要將編碼逆序

reverse

(currentcode.

begin()

, currentcode.

end())

; huffmancodeup.

push_back

(currentcode)

; currentcode.

clear()

;}}//從根節點開始求每個字元的huffman編碼

void

huffmancodingdown()

while

(currentnodeindex!=0)

//如果乙個節點的左右子樹都為空則為葉子節點,得到相應節點的編碼字串

else

if(temptreenodes[currentnodeindex]

.getrightchild()

==0)}

//節點已經被訪問過一次,向右邊進發

else

if(temptreenodes[currentnodeindex]

.getweight()

==1)}

//節點已經被訪問過兩次則返回其父節點

else}}}};

//測試程式

intmain()

赫夫曼樹和赫夫曼編碼

赫夫曼樹 1 先把有權值的葉子節點按照從小到大的順序排成乙個有序序列,即 a 5 e 10 b 15 d 30 c 40 2 取前兩個權值最小的結點即a 5 和e 10 作為乙個新的結點n1的兩個子節點,結點權值較小的作為左結點,即a為左結點,e為右結點,n1的權值為兩個結點權值的和,即5 10 1...

赫夫曼樹和赫夫曼編碼

include define maxsize 128 字元表 typedef struct table 哈夫曼樹節點 typedef struct hfmtree 哈夫曼編碼 typedef struct hfmcode hfmtree hdata 2 maxsize 1 hfmcode code ...

赫夫曼樹與赫夫曼編碼

問題描述 利用huffman編碼進行通訊可以大大提高通道利用率,縮短資訊傳輸時間,降低傳輸成本。但是,這要求在傳送端通過乙個編碼系統對待傳資料預先編碼,在接受端將傳來的資料編碼進行解碼 復原 對於有些通道,每端都需要乙個完整的編 解碼系統。試為這樣的資訊收發站編寫乙個huffman的編 解碼系統。給...