演算法是自己作為程式師開發比較薄弱的地方, 之前大學的時候也沒有好好學, 工作中具體用到的也很少。 但我深知演算法是程式師這個行業, 真正有意義的地方, 搬磚似得碼農到處都有, 但如果你會點演算法, 可能一次可以搬兩塊磚也說不定。 所以, 我決定今天起, 開始認真整理和演算法相關的一些東西, 作為自己的一點成長, 一點積累。 也歡迎大家關注我, 一起討論, 一起進步。
霍夫曼編碼壓縮演算法, 是資料壓縮中經典的一種演算法。 這是一種根據文本字元出現的頻率, 重新對字元進行編碼,
假設我們有這樣的一段資料需要進行編碼——“beep boop beer!”。 這段字元通過ASCII編碼後的結果為62 65 65 70 20 62 6F 6F 70 20 62 65 65 72 21 (十六進位), 總共有十五個位元組。
首先, 我們先計算每個字元出現的頻率, 經過我們統計, 得到下面一張表:
然後把這些數放到優先順序佇列中,
下面我們需要把這個佇列,
轉換成霍夫曼二叉樹,
這是一個帶有權重的二叉樹,
在佇列中每個字元出現的次數,
標識這個字元的權重,
霍夫曼二叉樹始終保證權重高的在越高的地方。
下面來介紹,
二叉樹是如何演變的。
我們從最左邊開始, 取兩個元素來構造一個二叉樹(第一個元素是左結點, 第二個是右結點), 並把這兩個元素的權重相加, 得到新的空元素。
同理, 我們繼續取最左邊兩個元素, 進行權重相加(2+2=4), 相加結果變大, 需要對權重進行重新排序。
繼續執行同樣的操作,
這裡可以看到自底向上的構建二叉樹的一個過程。
最後, 我們得到這樣一個帶有權重的二叉樹:
這裡, 我們把這個樹的左邊分支用0編碼, 右邊分支用1, 這樣我們就可以遍歷這棵二叉樹獲取每個字元的編碼, 例如:‘b’的編碼是 00, ’p’的編碼是101, ‘r’的編碼是1000。 我們可以發現出現次數越多的字元會越在上層, 它的編碼也越短, 次數少的字元, 編碼越長。
最後我們可以得到下面這張編碼表:
利用這個編碼表我們對字串“beep boop beer!”重新進行編碼,得到:0011 1110 1011 0001 0010 1010 1100 1111 1000 1001。共計40位元二進位,而之前沒重新編碼時,是15位元組共120位元,這樣看來壓縮比例還是比較客觀的。
最後我們可以得到下面這張編碼表:
利用這個編碼表我們對字串“beep boop beer!”重新進行編碼,得到:0011 1110 1011 0001 0010 1010 1100 1111 1000 1001。共計40位元二進位,而之前沒重新編碼時,是15位元組共120位元,這樣看來壓縮比例還是比較客觀的。