最近須要把採集到的圖像數據進行壓縮,節省存儲空間。綜合考慮壓縮比和速度,決定採用靜態Huffman編碼,使用預先計算好的字典對數據進行壓縮,這樣壓縮速度能夠很是高,使用多線程以後能夠進行實時壓縮,但解壓速度比較慢。html
因而去gzip的代碼裏面找了一下,在一個叫unpack.c
的文件裏發現了Huffman解碼的實現,gzip的解碼確實很高效,其中的緣由,簡單來講就是多用內存,少用循環。多線程
假設咱們要壓縮的字符串是「ABBBCC」,計算獲得Huffman編碼以下:編碼
字符 | 計數 | 編碼 |
---|---|---|
A | 1 | 00 |
B | 3 | 1 |
C | 2 | 01 |
編碼後的二進制串是 0011101線程
要對編碼後的字符串進行解碼,比較容易想到的方法是這樣的,構造這麼一個字典code
編碼 | 字符 |
---|---|
1 | B |
00 | A |
01 | C |
這個字典是原始的編碼表按字符編碼的長度進行排序,解碼的時候就在字典裏面順序地查找編碼htm
對於這個例子而言是這樣一個過程排序
對二進制串0011101從左往右解碼,先嚐試編碼1(對應字符B),發現不對,由於最左邊是0,所以再嘗試字典的第二個編碼00(對應A),發現是正確的,最左邊就是00,所以解碼出字符A,將二進制串左移兩位獲得11101,繼續從B的編碼1開始嘗試。最後能解碼出ABBBCC這個原始編碼。索引
這個解碼方法的問題就是每解碼一個字符串都要在字典裏面循環一遍,效率不高。ip
對於咱們的例子gzip會構造這麼一個字典內存
索引 | 索引編碼 | 編碼 | 字符 |
---|---|---|---|
2 | 10 | 1 | B |
3 | 11 | 1 | B |
0 | 00 | 00 | A |
1 | 01 | 01 | C |
這個字典的特色就是有索引,所以查找編碼的時候不用循環,而是計算索引直接定位到對應的編碼。字典的構造方法是根據編碼生成索引編碼,全部索引編碼的長度是相同的,從二叉樹的角度來看就是把全部的子樹都補到一樣的長度,而後全部非編碼節點(如11)都和其父節點(如1)對應同一個字符(如B)。
這個方法一樣也是一種空間換時間的方法,隨着編碼長度的增長,內存消耗會指數增加,所以當編碼太長時,gzip會使用多個字典,將長編碼放在一些單獨的字典裏面,減少內存消耗。