哈弗曼樹與哈弗曼編碼(實現)

2021-09-26 14:17:24 字數 2765 閱讀 8774

歷史背景

2023年,霍夫曼在mit攻讀博士學位,他和修讀資訊理論課程的同學得選擇是完成學期報告還是期末考試。導師robert fano出的學期報告題目是:查詢最有效的二進位制編碼。由於無法證明哪個已有編碼是最有效的,霍夫曼放棄對已有編碼的研究,轉向新的探索,最終發現了基於有序頻率二叉樹編碼的想法,並很快證明了這個方法是最有效的。使用自底向上的方法構建二叉樹避免了次優演算法夏農-范諾編碼的最大弊端──自頂向下構建樹。

哈弗曼編碼

在計算機資料處理中,霍夫曼編碼使用變長編碼表對源符號(如檔案中的乙個字母)進行編碼,其中變長編碼表是通過一種評估**符號出現機率的方法得到的,出現機率高的字母使用較短的編碼,反之出現機率低的則使用較長的編碼,這便使編碼之後的字串的平均長度、期望值降低,從而達到無失真壓縮資料的目的。簡而言之,採用哈弗曼編碼的資料wpl最短。

什麼是樹的帶權路徑長度 wpl

樹的帶權路徑長度,就是樹中所有的葉結點的權值乘上其到根結點的路徑長度(若根結點為0層,葉結點到根結點的路徑長度為葉結點的層數)。樹的路徑長度是從樹根到每一結點的路徑長度之和,記為wpl=(w1 * l1+w2 * l2+w3 * l3+…+wn * ln),n個權值wi(i=1,2,…n)構成一棵有n個葉結點的二叉樹,相應的葉結點的路徑長度為li(i=1,2,…n)。

維基百科圖示

哈弗曼樹的構建

假設有n個權值,則構造出的哈夫曼樹有n個葉子結點。 n個權值分別設為 w1、w2、…、wn,則哈夫曼樹的構造規則為:

(1) 將w1、w2、…,wn看成是有n 棵樹的森林(每棵樹僅有乙個結點);

(2) 在森林中選出兩個根結點的權值最小的樹合併,作為一棵新樹的左、右子樹,且新樹的根結點權值為其左、右子樹根結點權值之和;

(3)從森林中刪除選取的兩棵樹,並將新樹加入森林;

(4)重複(2)、(3)步,直到森林中只剩一棵樹為止,該樹即為所求得的哈夫曼樹。

哈弗曼編碼
1.給霍夫曼樹的所有左鏈結』0』與右鏈結』1』。

2.從樹根至樹葉依序記錄所有字母的編碼。

詳細過程

實現霍夫曼編碼的方式主要是建立乙個二叉樹和其節點。這些樹的節點可以儲存在陣列裡,陣列的大小為符號(symbols)數的大小n,而節點分別是終端節點(葉節點)與非終端節點(內部節點)。

一開始,所有的節點都是終端節點,節點內有三個字段:

1.符號(symbol)

2.權重(weight、probabilities、frequency)

3.指向父節點的鏈結(link to its parent node)

而非終端節點內有四個字段:

1.權重(weight、probabilities、frequency)

2.指向兩個子節點的 鏈結(links to two child node)

3.指向父節點的鏈結(link to its parent node)

基本上,用』0』與』1』分別代表指向左子節點與右子節點,最後為完成的二叉樹共有n個終端節點與n-1個非終端節點,去除了不必要的符號並產生最佳的編碼長度。

過程中,每個終端節點都包含著乙個權重(weight、probabilities、frequency),兩兩終端節點結合會產生乙個新節點,新節點的權重是由兩個權重最小的終端節點權重之總和,並持續進行此過程直到只剩下乙個節點為止。

**部分

#include

#include

#include

#include

using

namespace std;

const

int size =10;

struct node

;deque

> forest;

deque<

bool

> code;

node *ptr;

int frequency[size]=;

void

printcode

(deque<

bool

> ptr)

;// 輸出哈弗曼編碼

bool

compare

( node *a, node *b)

intmain

(int argc,

char

*ar**)

// 形成森林,森林中的每一棵樹都是乙個節點

// 從森林構建哈弗曼樹

for(

int i =

0; i < size -

1; i++

) ptr = forest.

front()

;// ptr是指向根的指標

system

("pause");

return exit_success;

}void

printcode

(deque<

bool

> ptr)

}

哈弗曼編碼 哈弗曼樹

哈弗曼編碼是依賴於字元使用頻率來建立的一種編碼,通過把使用頻率低的字元分配相對較多的01編碼,而使用頻率高的分配相對較低的01編碼,來建立最小的帶權路徑長度的樹,來最大化的獲得編碼儲存空間的一種編碼規則。這個樹稱為哈弗曼樹,也稱為最優二叉樹。這樣可以確定每乙個字元的編碼不可能成為其他字元編碼的坐子串...

哈弗曼編碼

include include include define my strmax 100 define infinity 1000000 typedef struct htnode,huffmantree 動態分配陣列儲存赫夫曼樹 typedef char huffmancode 動態分配陣列儲存赫...

哈弗曼編碼

include iostream include queue include vector include string using namespace std struct huffmantree bool operator const huffmantree t const vector h 相...