哈夫曼編碼
完整**
哈夫曼樹是一類帶權路徑長度最短的樹,通過對哈夫曼樹的構建,可以實現資料的編碼最短且不同資料編碼之間互不為前字尾的效果。
根據給定的n
nn個權值
\構造n
nn棵只有根節點的二叉樹,並令其權值為wi(
i=1,
2,…,
n)w_i (i =1,2,\dots ,n)
wi(i=
1,2,
…,n)
。在這些二叉樹所組成的森林中選取兩棵節點權值最小的樹分別為其左右子樹(約定左子樹權值不大於右子樹)構建一棵新的二叉樹。
在森林中刪除選中的兩棵樹,並將合併後的二叉樹加入森林中。
重複2 、3
2、32、
3步,直至只有一棵二叉樹,即哈夫曼樹。
舉個例子:
給定五個資料
\,其權值分別為
**中,將哈夫曼樹儲存在vector中進行演示;
若使用陣列形式,可在建構函式內動態申請陣列空間(記得在析構函式中釋放);
以下**中使用了模板,其中k代表需要構建哈夫曼樹的資料的資料型別,v代表其權值的資料型別;
哈夫曼樹結構體的定義:
struct
htnode
;
由於哈夫曼樹中沒有度為1
11的節點,則一棵具有n
nn個葉子節點的哈夫曼樹共有2n−
12n-1
2n−1
個節點。
vector初始化:
擴容到2n−
12n-1
2n−1
個空間,並將所有單元中的雙親及左右孩子的下標初始化為−1-1
−1,並將前n
nn個單元的權值及資料儲存下來。
建立哈夫曼樹:
進行迴圈n−1
n-1n−
1次操作來實現選擇、刪除與合併操作來建立哈夫曼樹,其中:
計算樹的帶權路徑長度:
可以通過遞迴的方式向下進行
選擇出最小節點的函式:
void
getmin
(int n,
int& s1,
int& s2)
else}}
if(ht[s1]
.value > ht[s2]
.value)
//尋找到最小的兩個節點,並保證s2不小於s1
for(i +=
1; i < n; i++
)else
if(ht[i]
.value < ht[s2]
.value)}}
}
計算帶權路徑長度的函式:
int
huffmantreewpl
(int i,
int dep)
else
}
構建哈夫曼樹的函式:
huffmantree
(vector
& hdata, vector
& hvalues)
for(
int i =
0; i < datanum; i++
)//構建哈夫曼樹
for(
int i = datanum; i < maxnodes; i++
)//計算帶權路徑長度
wpl =
huffmantreewpl
(maxnodes -1,
0);}
從根節點開始,左子樹編碼為"0",右子樹編碼為"1",從根節點到該節點所經過的編碼連起來就是該節點的哈夫曼編碼。
舉個例子:(對剛才構建的哈夫曼樹進行編碼)
完成哈夫曼編碼:
從葉子節點出發向上探尋,若為左孩子,則增加字首編碼"0",若為右孩子,則增加字首編碼"1"
注:增加字首編碼的原因是哈夫曼編碼從根節點開始,而實現時從葉子節點開始,方向相反,故通過增加字首的方式實現編碼
對資料進行哈夫曼編碼的函式:
void
computedhuffmancode()
else
j = parent;
}//存入map中方便查詢
huffmancode.
insert
(pair
(ht[i]
.data, code));
}}
#
pragma
once
#include
#include
#include
template
<
classk,
class
v>
class
huffmantree
for(
int i =
0; i < datanum; i++
)//構建哈夫曼樹
for(
int i = datanum; i < maxnodes; i++
)//計算帶權路徑長度
wpl =
huffmantreewpl
(maxnodes -1,
0);//計算哈夫曼編碼
computedhuffmancode()
;}/** *返回帶權路徑長度
*/intgetwpl()
/** *返回全部哈夫曼編碼
*/std::map
getallhuffmancode()
/** *返回特定data的哈夫曼編碼
*該data不存在該哈夫曼樹中,返回空字串
*/std::string gethuffmancode
(k data)
private
:struct
htnode
;int datanum;
//需要編碼的資料數量
int maxnodes;
//樹需要的最多節點數量
int wpl;
//帶權路徑長度
std::vector ht;
//哈夫曼樹
std::map huffmancode;
//哈夫曼編碼
/** *尋找當前兩個權值最小的樹
*/void
getmin
(int n,
int& s1,
int& s2)
else}}
if(ht[s1]
.value > ht[s2]
.value)
//尋找到最小的兩個節點,並保證s2不小於s1
for(i +=
1; i < n; i++
)else
if(ht[i]
.value < ht[s2]
.value)}}
}/**
*計算帶權路徑長度
*/inthuffmantreewpl
(int i,
int dep)
else
}/**
*計算哈夫曼編碼
*/void
computedhuffmancode()
else
j = parent;
}//存入std::map中方便查詢
huffmancode.
insert
(std::pair
(ht[i]
.data, code));
}}};
哈夫曼樹與哈夫曼編碼
在一般的資料結構的書中,樹的那章後面,著者一般都會介紹一下哈夫曼 huffman 樹和哈夫曼編碼。哈夫曼編碼是哈夫曼樹的乙個應用。哈夫曼編碼應用廣泛,如 jpeg中就應用了哈夫曼編碼。首先介紹什麼是哈夫曼樹。哈夫曼樹又稱最優二叉樹,是一種帶權路徑長度最短的二叉樹。所謂樹的帶權路徑長度,就是樹中所有的...
哈夫曼樹與哈夫曼編碼
1.哈夫曼 huffman 編碼是哈夫曼樹的乙個應用。2.哈夫曼樹又稱為最優二叉樹,是一種帶權路徑長度最短的二叉樹。所謂樹的帶權路徑長度,就是樹中所有的葉結點的相對值乘上其到根結點的路徑和權值。3.影象jpg就是利用了哈夫曼編碼。4.哈夫曼樹是最優二叉樹,子樹有左右次序之分。5.哈夫曼樹的形態不是唯...
哈夫曼樹與哈夫曼編碼
哈夫曼樹是一種簡單的樹結構,建樹過程如下 給出一組資料,不斷選擇最小的兩個數,並用兩個數的和作為它們的parent節點,再從資料中刪除這兩個數,將兩個數的和加入資料中,直到所有的資料都被加入樹結構,形成一顆樹。這顆樹的所有非葉子節點都有兩個child,兩個child的值的和則是這個節點的值,根節點是...