1.前綴編碼
首先對於一個串可以用等長的二進制位表示,這樣就叫做固定長度編碼。如果可以用不等長的二進制位表示,則稱之爲可變長度編碼。那麼對於那些頻度高的字符我們採用短二進制位編碼,出現頻度低的採用長二進制位編碼的話,將會極大地減少編碼長度,起到壓縮數據的作用。
在一個編碼方案中,沒有一個編碼是另外一個編碼的前綴,則稱這個編碼方案爲前綴編碼。對前綴編碼的解碼很簡單,因爲沒有一個碼是其他編碼的前綴,所以識別出第一個編碼翻譯爲原碼,再對後續的編碼文件重複進行同樣的操作。比如0,101,100就是一組前綴編碼。00100101,就可以唯一的被識別爲0,0,100,101。而不會產生二義。
引入前綴編碼的話就是想用一組能唯一標識的編碼來表示原數據,並且數據所佔空間最小。
編碼 | 等長編碼 I | 不等長編碼 II | 不等長編碼 III |
---|---|---|---|
a | 000 | 0 | 0 |
b | 001 | 1 | 101 |
a | 010 | 10 | 100 |
d | 011 | 11 | 111 |
e | 100 | 101 | 1101 |
1.對於等長編碼5個字符來說,就需要至少3位,因爲22=4,23=8纔夠用,就會浪費很多空間。
2.對於不等長編碼I,abcde編碼後就是011011101,那麼在解碼的時候就會出現0,11,0,11,101或者0,11,0,1,11,0,1等等其他錯誤的序列。
3.然後就出現了不等長編碼III,abcde編碼後序列就是01011001111101,解碼的時候0,101,100,111,1101還原abcde不會出現二義。
所以編碼II就不是前綴編碼,編碼III是前綴編碼。
總之就是[1]採用不等長的編碼方式就是爲了壓縮。[2]利用前綴編碼就是解決能否唯一標識的問題。
2.哈夫曼編碼與哈夫曼樹
哈夫曼編碼就是由哈夫曼樹順理成章得到的,上面說到了想要利用短二進制位去表示出現頻度較高的字符從而達到壓縮的效果。
2.1 首先Huffman樹就是帶權路徑最小的二叉樹稱之爲哈夫曼樹,也叫最優二叉樹。它的葉結點都是帶有權值的,帶權路徑就是從葉結點出發到達根節點的路徑數權值,就是該葉結點的帶權路徑,哈夫曼樹保證所有葉結點的帶權路徑和最小。
WPL=∑wi*li.
以下圖爲例,a結點的帶權路徑值就是451=45,b結點帶權路徑值就是13*3=39。
2.2 然後說哈夫曼樹如何構造:
首先已知各個節點的權值,現在所期望的就是帶權路徑和最小。所以對於權值較大的結點我們肯定希望它的路徑短。
對於所有節點,我們先把每一個節點都設爲一個根節點,這樣就形成了n顆只有根節點的樹了。
然後把權值最小的兩棵樹結合到一起,生成一個新的根節點,把兩棵樹的權值和作爲新的樹的根節點的權值。
對於新的森林重複上一操作,直到整個森林只剩下一棵樹的時候。
以上圖爲例:
1.首先已知abcdef的權值,a(45)、b(13)、c(12)、d(16)、e(9)、f(5)。然後找到權值最小的兩棵樹f和e構成一顆新樹,權值爲f+e=14。
2.對於新的森林找到權值最小的兩棵樹c和b構成一顆新的樹,權值爲c+b=25。
3.重複操作,直到得到上面的那棵樹。
2.3對於構造好的哈夫曼樹,令左子樹編碼爲0,右子樹編碼爲1(也可以相反)。從根結點出發到達葉結點就可以得到哈夫曼編碼:
a:0
b:101
c:100
d:111
e:1101
f:1100
這樣的話存儲的位數就是WPL=1*45+3*13+3*12+3*16+4*9+4*5=224位。
而用等長編碼的話,abcdef一共6個字符,至少需要3位(23=8),得到的二進制編碼位數爲3*(45+13+12+16+9+5)=300位。
這裏共壓縮了25%的數據,這就是哈夫曼編碼的作用。哈夫曼樹可以設計出總成都最短的二進制前綴編碼。