哈夫曼的編碼與解碼邏輯過程

2021-09-03 07:09:33 字數 3450 閱讀 1529

哈夫曼的編碼與解碼邏輯過程

編碼有三個大的步驟

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)編碼與解碼

利用哈夫曼編碼進行資訊通訊可以大大提高通道利用率,縮短資訊傳輸時間,降低傳輸成本。但是,這要求在傳送端通過乙個編碼系統對待傳輸資料預先編碼,在接收端將傳來的資料進行解碼。對於雙工通道,每端都需要乙個完整的編碼 解碼系統。試為這樣的資訊收發站寫乙個哈夫曼的編 解碼系統。乙個完整的系統具有以下幾種操作 ...