對於 binary tree ,原本指向 NULL
的節點,讓它改成指向一種特別的節點
原本那棵 binary tree 的節點被稱為 internal nodes ,那些特殊的節點則為 external nodes
定義 為樹 之 internal path length,即 之所有 internal nodes 深度之總和
定義 為樹 之 external path length,即 之所有 external nodes 深度之總和
則
其中 為 internal nodes 總數
這個可以輕鬆用數學歸納法證明出來,在此不贅述
給予 個 external node weight values
定義從 root 到 external node 之 path length 為
由此可發現,樹高縮小, 不見得變小
那麼要怎麼求出最小的 呢?
使用 greedy 的策略
Huffman Coding 是種最佳方法,其每個輸入符號通常是具有二元機率的已知獨立且相同分布的隨機變數
Huffman code 是 variable-length code,即其編碼結果長度不見得都相同長
我們目標是 最小,如果以字母出現頻率(或者說機率)作為權重,則出現頻率越高的字母,編碼長度應會越短
這樣的特色使得編碼之後的字串的平均長度、期望值降低,而甚至能達到無失真壓縮數據
Tip
那麼,對於具有均勻機率分布的一組符號,以及作為 的冪之成員,Huffman Coding 的效益如何呢?
此時 Huffman Coding 的效果等同於簡單的二進位制編碼,例如 ASCII code
這邊反映出的事實是:無論壓縮方法是什麼,這種輸入都不可能進行壓縮,或著說比起壓縮,對數據無所作為才是最佳選擇
另外,Prefix code,特別是 Huffman code,往往在小字母表上的效率較差
當最可能符號的機率遠超過 時,Huffman Coding 可能會遇到 worst case
Huffman encode 的演算法相當好懂:
每次我們挑最小的兩個 weight (可以用 Min-Heap) 把兩者相加的值作為新節點再塞回 Min-Heap
總共執行 n-1
次,每回合花 故時間複雜度是
以下是個簡易版的實現:
Min-Heap 使用我們前面製作的 binary heap (標準庫有提供 std::prioirty queue
但我們都自己寫了一個玩具版了,為何不用呢?)
我們 input
給定 "BDCAE"
,各字母頻率如下:
Character | A | B | C | D | E |
---|---|---|---|---|---|
Frequency | 22 | 3 | 10 | 5 | 60 |
來看看結果