適應性霍夫曼編碼
适应性霍夫曼编码(英語:),又称动态霍夫曼编码(),是基於霍夫曼编码的適自适应编码技术。它允许在符号正在传输时构建代码,允许一次编码并适应数据中变化的条件,即随着数据流的到达,动态地收集和更新符号的概率(频率)。一遍扫描的好处是使得源程序可以实时编码,但由于单个丢失会损坏整个代码,因此它对传输错误更加敏感。
在霍夫曼編碼中,有個缺點是除了壓縮後的資料外,它還得傳送機率表給解碼端,否則解碼端無法正確地做解碼的工作。如果想要壓縮好一點,必須有更多的統計資料,但同時必須要送出更多的統計資料到解壓縮端。而適應性編碼可以利用已經讀過的資料機動的調整霍夫曼樹。適應性霍夫曼編碼中,演算法FGK的基本原則是根據兄弟性質(Sibling Property),由Gallager定義。
兄弟性質
一顆霍夫曼樹只是一棵在每個節點,包括樹葉與內節點,加上加權值的二元樹,除了樹根外,每一個節點都有一個兄弟節點與其共有一個父親節點。如果每一個節點可以按照加權值從小排列到大且每個節點又再自己的兄弟相鄰,稱為兄弟性質。修改、或更新一棵霍夫曼樹包括兩個步驟。第一個步驟是頻率次數的增加,先找到該葉子,把頻率加一,在往上找他的父親節點,也跟著加一,直到樹根皆照著此步驟。第二個步驟是如果增加加權值的動作使得兄弟性質不再滿足時,必須做調整的動作,藉由交換葉子改變頻率增加的順序,同時,交換位置後的父親節點加權值也要跟著更新,以此原則使之再度成為霍夫曼樹。
FGK演算法
在演算法FGK中,傳輸端與接收端同時動態的去改變霍夫曼樹,最初,解碼樹由單一葉子組成,稱之0端。0端是用來代表未出現過的訊息,當每一個訊息傳遞後,增加此訊息的出現頻率並調整霍夫曼樹保持兄弟性質。當有t個訊息傳遞後,之中有k個不同的訊息,代表此霍夫曼樹有k+1的葉子,k個葉子有訊息,1個代表0端。當下次傳遞新訊息時,此訊息夾帶未出現過的資訊,0端的葉子此時分成2片葉子,1片給新訊息,另一片為新的0端。
考慮適應性霍夫曼編碼的效能問題,更有效能的方法是確認編碼端不會浪費空間在不存在的符號上,一般的霍夫曼編碼容易做到是因為在建立霍夫曼樹之前,會統計所有的資料,就能先算出各訊息的頻率;相反的,適應性編碼不一樣,並不知資料出現的頻率,因此假設所有訊息長度都一樣是log_2q個位元,伴隨著統計資料的增加,訊息的編碼長度會愈來愈短。但此方法有個缺點,在大部分情況會浪費許多空間,尤其在短訊息的情況,大部分未使用的符號會改變整個統計表,使得壓縮結果大打折扣。
舉例來說,符號源有256個符號,一開始的霍夫曼樹就有這256個符號,且加權值設為1,即使連續讀進16個e,也仍然需要四個位元以上來編碼e,因為其他沒出現的255個符號使得霍夫曼樹的調整速度變慢。
解決的方法可以一開始統計表都沒有東西,當訊息被讀進去時在加入到統計表內,假設一開始霍夫曼樹只有兩個符號,兩個符號加權值都是一,且都不改變,一個代表檔案結束,另一個符號較特別,如果辨識的符號,霍夫曼樹已經有了,就像上述正常的操作,如果霍夫曼樹沒出現過,先送出此符號,再送出此符號的ASCⅡ碼,最後將這個加入霍夫曼樹,設定加權值為1,調整霍夫曼樹。這種方法,如過訊息是連續16個e,除了第一個e是九個位元,後面的所有15個e都只需要一個位元表示。
Vitter演算法
編碼一樣是用樹狀結構表示,每個支點都有對應的權重及特定數字,數字從上到下、從左到右排列,權重要遵守兄弟性質,如果A是B的父親且B是C的父親,則。
權重用來計算支點編碼及其小孩(底下的支點)的數量,一樣權重的胝點會形成一個區塊,要得到每個支點的編碼,在二進位樹上,傳輸所有從樹根到此支點的路徑,往右走就寫1,往左走就寫0。需要有系統且簡單的方式去表示還沒傳遞(NYT),可以使用字母去傳遞二進位數字,編碼跟解碼都是從一個有最大數字的樹根開始,當傳遞NYT時,必須傳遞編碼到NYT支點,接著是普遍的支點,當每一個符號都完成後,只要傳遞編碼到自己的葉子支點即可。
參考來源
- 資料壓縮,戴顯權編著
- Vitter's original paper: J. S. Vitter, "Design and Analysis of Dynamic Huffman Codes", Journal of the ACM, 34 (4), October 1987, pp 825–845.
- J. S. Vitter, "ALGORITHM 673 Dynamic Huffman Coding", ACM Transactions on Mathematical Software, 15 (2), June 1989, pp 158–167. Also appears in Collected Algorithms of ACM.
- Donald E. Knuth, "Dynamic Huffman Coding", Journal of Algorithm, 6 (2), 1985, pp 163-180.