"一、簡介:
資料的儲存和傳輸式資料處理的兩個重要的領域,它們都和資料量的大小息息相關,尤其是網際網路何多媒體結合的情況下,如何讓龐大的資料順利的流通於有限的頻寬上,更是重要的議題,同樣的資訊內容,如果我們可以用更少的資料來表示,不論是在儲存或是傳輸上都有很大的幫助,這就是資料壓縮的想法。
[@more@]
我們已ASCII為例,一般在做資料儲存時,每一個文字都是一個位元組(byte),也就是八個位元(bit) ,但是實際上每個文字都使用頻率相差很大,我們如果用不同長度的位元數來儲存這些資料,也就是出現頻率越高的字母其長度越短,頻率越低的字其長度則越長,其資料量也就能大幅減少了。當然資料壓縮之後,字母和內碼依然是對應的,最後可以完全還原,才不至於改變資訊的內容。
二、霍夫曼樹介紹:
我們將使用二元數來進行資料壓縮的演算法,稱為霍夫曼(Huffman)編碼,這棵二元數也就稱為霍夫曼樹,它是根據每一個字母出現的頻率,重新定義一個字母的內碼,而每個字母的內碼並不完全相等,霍夫曼演算法相當的減當,而壓縮效果也很理想,根據實驗,霍夫曼演算法大概可以得到50%左右的壓縮率。
首先我們先介紹幾個相關的名詞,內部路徑長(internal path length)是指由數根到每個內部節點的路徑長度總和;外部路徑長(external path length) 是指由數根到每個外部節點的路徑長度總合;所以一棵如底下圖的二元樹,其內部路徑長度為 1 + 2 + 1 + 2,外部路徑長度為 2 + 3 + 3 + 2 + 3
如果每一個數夜節點都賦予一個加權數(weight),每一個數葉節點的加權數乘上其路徑長的總和就稱為加權路徑長(weighted path length),所以如果上圖節點加權數分別為 0.19*2 + 0.03*3 + 0.21*3 + 0.12*2 + 0.39*3 = 2.69 就是這棵樹的加權路徑長。
霍夫曼邊每的想法非常簡單,每一個字母出現的頻率就是他的加權數,將這些字母一一放到二元樹的樹葉節點,從根節點到數葉節點所走過的路徑就是他的編碼規則,如果路徑是往左邊,則編碼則為 0,往右邊則為1 ,所以上圖的每一個字母編碼分別為 00、010、011、10、110,霍夫曼編瑪就是要產生一棵最小的加權路徑長的二元樹,這棵二元樹將會讓我們得到更好的壓縮效果。
三、霍夫曼樹建立:
我們一開始將每個字母分別建成只有一個根節點的二元樹,根據其頻率由小到大排序;取出最前面的兩個節點,將它們分別連結到另一棵新的二元樹的左右子樹,新二元樹根節點就是左右子束的頻率和,依照新二元樹的頻率大小放回元串列中,並保持該串列由小到大的特性;重複上面的步驟直到所有節點都處理完畢為止。
假設 A、B、C、D、E五個字母的頻率分別為 0.19、0.09、0.21、0.12、0.39
那們我們先將他們依序排列如下:
|
0.09 |
0.12 |
0.19 |
0.21 |
0.39 |
|
B |
D |
A |
C |
E |
霍夫曼樹建立過程如下:
1. 取出最小的0.09和0.12,合併成另外一棵新的二元樹,其根節點的頻率為0.21
2. 在取出0.19和0.21合併後在得到0.10的新二元樹
3. 取出 0.21 和0.39的節點,產生頻率為0.60 的新節點
4. 最後在取出0.40和0.60 的節點,合併成頻率為1.0的節點,至此霍夫曼二元樹就算完成了
霍夫曼資料壓縮演算法的過程,首先是根據資料的出現頻率,建立一棵霍夫曼二元樹,其次根據這棵二元樹的走訪,建立一個字元與新碼的對照表,有了這個對照表,我們就能將一個ASCII碼的字元檔案轉換成新內碼的檔案,最後要將這個新內碼的檔案還原成為新的字元檔,同樣要以同一棵霍夫曼樹來解碼。
四、結論:
就以霍夫曼數的編碼模式的壓縮效率來說,並非為效率非常高的壓縮方式。假設以8位元資料為一個單位來說,無論壓縮的在怎麼好,頂多也子能壓縮到1/8而已。若將更多的位元來表示更多的位,也許會有更好的壓縮效率,但此時所出現的頻率表亦也會更大,故壓縮效率也無法提升到哪裡去。
也因為霍夫曼編碼有這樣的缺點,縮以此編碼方式一般皆不會拿來單獨使用,而長與其他的壓縮演算法配合使用。舉個例子來說,如常用的「LHA」當中就是以『霍夫曼編碼』與『LZ法』搭配使用。再例如,用於圖像的JPEG格式中最後要做編碼的時候,也常會使用霍夫曼來提升壓縮率。
"