哈夫曼的編碼與解碼邏輯過程
編碼有三個大的步驟
1統計原檔案的符號的出現的頻率,按照頻率進行公升序排列。
頻率相同的,按照被編碼的符號的公升序排列。
構造哈夫曼編碼的二叉樹。
合併最小值的兩項,用新合併後的集合替換原有的兩項,新項的頻率等於原來兩項的和。
繼續合併,直到只剩下一項為止。
(因為需要頻繁地刪除結點,並且把新增加的結點插入到指定的位置上,來保證乙個有序的集合。
所以採用的了雙向的鍊錶的方向。根據原來的儲存資料的陣列,構造乙個新的雙向的鍊錶,而且它有頭結點。
儲存資料的陣列,只做新增結點的操作。
新增結點時,先在原來的儲存資料的陣列中新增結點,並且是直接新增在陣列的最後邊。
然後在雙向鍊錶中,查詢到合適的位置,並且插入這個新增的結點,並且把它指向儲存資料
的陣列中的對應的資料。
刪除結點時,只刪除雙向鍊錶中的結點。
操作的詳細過程是先初始化雙向鍊錶。然後開始對雙向鍊錶進行迴圈性的操作。
結束條件是,除了頭結點以外,雙向鍊錶中只有乙個結點了。
取出雙向鍊錶中的前兩個結點,根據它們構造乙個新的結點,利用這三個結點構造子樹。
然後新增加結點。再刪除雙向鍊錶中的前兩個結點。
)2根據二叉樹,構造碼表
對二叉樹進行先根序的遍歷,對所有的葉子結點進行遍歷,每遍歷到乙個葉子結點,
輸出碼表的一條記錄。
從樹根開始,在二叉樹上的所有的結點上,新增加乙個域,儲存比**。這個域,樹根為空。
左子樹的結點在父結點的比**最右面追加乙個0,
左子樹的結點在父結點的比**最右面追加乙個1,直到葉子結點。就得到了葉子的比**。
即某個被編碼的符號對應的比**。
對於非葉子結點,還有要乙個記錄是否遍歷過它的子結點的標識。
有三種情況如下:
@1. 初到該結點時標識為0,並且設定比**。然後去它的左子結點。
從該結點下到左子結點時,這個標識設定為1,
@2. 從子結點回到該結點時,標識為1 則去它的右子結點,
從該結點下到右子結點時,這個標識設定為2,
@3. 從子結點回到該結點時,標識為2,則去它的父結點。
對於葉子結點,設定比**。並且輸出這個比**。返回父結點。
3編碼對要編碼的源文字根據碼表,一一替換即可。
哈夫曼編碼過程的函式的依賴關係圖如下:
解碼有三個大的步驟
1得到碼表
根據碼長轉換成哈夫曼的碼表的程式得到結果,作為本程式的輸入內容。
2構造碼表的二叉樹
定義二叉樹的結點的資料結構。它是葉子結點時[0,父結點的索引,編碼的值]
它是非葉子結點時[1,父結點的索引,左子結點的索引,右子結點的索引],
如果乙個子結點不存在,相應的索引的位置寫-1。
整個二叉樹儲存在陣列中,每個結點是其中的乙個元素,元素的資料下標
就是這個結點對應的被引用的索引。
構造過程
初始化為只有乙個根結點的狀態 即 [[2,-1,-1,-1]]
讀入二進位制的碼表的位元流,迴圈處理其中的每個符號代表的子串,
對於子串,逐位讀取,如果是0,檢查當前所在結點的左子結點是否存在
如果是1,檢查當前所在結點的右子結點是否存在。
如果子結點存在,就走到新的子結點位置,再讀取子串中的下一位。
如果子結點不存在,就建立這個新的子結點,並且當前結點記錄下左或者是
右結點的索引。這個索引值,就是新建結點的索引值。然後走到新的子結點位置。
子串中讀取的位如果不是最後一位,建立的子結點是非葉子結點。[1,當前結點的索引,-1,-1]
如果是最後一位時,建立的是葉子結點。[0,當前結點的索引,所代表的符號]
到此為止,代表乙個符號的位元子串處理完畢
在處理下乙個符號的子串時,當前結點返回到根結點開始。如上的過程,直到整個位元流結束。
3解碼讀取哈夫曼的二進位製碼的位元流,遍歷第二步構造的二叉樹,從根到了葉子,記錄下得到的解碼的符號值。
再從根開始遍歷,直到位元流的結束為止。
在遍歷到某個結點時,先判斷是否是葉子結點,如果是葉子結點,就輸出解碼的符號值,並且把指標指向根結點。
如果不是葉子結點,根據給定的下乙個0或者是1值,選擇相應的左或者是右子樹的結點,給迴圈返回相應的子結點。
哈夫曼解碼過程的函式依賴關係圖如下:
解碼的測試資料
哈夫曼的位元串 對應於所編碼的符號如下:
00 ----> 5
01 ----> 6
100 ----> 0
101 ----> 4
110 ----> 18
11100 ----> 1
11101 ----> 2
11110 ----> 3
11111 ----> 17
根據第二步驟的程式,得到的二叉樹的結果如下:
[[2,-1,1,4],[1,0,2,3],[0,1,5],[0,1,6],[1,0,5,8],[1,4,6,7],[0,5,0],[0,5,4],
[1,4,9,10],[0,8,18],[1,8,11,14],[1,10,12,13],[0,11,1],[0,11,2],[1,10,15,16],
[0,14,3],[0,14,17]]
第三步的測試資料
[1,1,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,0,0,1,1,0,1,0,1,1,0,0,0,1,0,0]
測試結果資料:
[17,3,2,1,18,4,0,6,5]
//----------------begin 2018-11-15 wangwei
function huffman_decode()
function huffman_decode_inner_do(huffman_tree,bit_stream)
function huffman_tree_foreward_step(result_arr,current_index,direction,val,j,str_length)
else
else
}return ;
}function huffman_code()
function huffman_code_inner_do(src_stream,code_val,bit)
{var result=;
for(var i=0;ifunction huffman_code_inner_do_make_result(result_arr,bit_str)
{var result=result_arr
for(var i=0;i//----------------end 2018-11-15 wangwei
哈夫曼編碼與解碼
include include include include define maxnum 60typedef struct huffnode typedef struct huffcode huffnode ht maxnum 2 存放哈夫曼樹 huffcode hcd maxnum 存放ht陣列...
哈夫曼編碼解碼
簡單實現編碼解碼功能 列印哈夫曼樹形 該怎麼做呢 求教!實現初始化,建立huffman樹,並完成字元的編碼 之前解碼用for迴圈不能夠重新復位遍歷 while更好用 include stdio.h include string.h define n 10 待編碼字元的個數,即樹中葉結點的最大個數 d...
哈夫曼(Huffman)編碼與解碼
利用哈夫曼編碼進行資訊通訊可以大大提高通道利用率,縮短資訊傳輸時間,降低傳輸成本。但是,這要求在傳送端通過乙個編碼系統對待傳輸資料預先編碼,在接收端將傳來的資料進行解碼。對於雙工通道,每端都需要乙個完整的編碼 解碼系統。試為這樣的資訊收發站寫乙個哈夫曼的編 解碼系統。乙個完整的系統具有以下幾種操作 ...