1. 程式人生 > 其它 >解壓zip_VBA解壓縮ZIP檔案06——Huffman樹碼錶

解壓zip_VBA解壓縮ZIP檔案06——Huffman樹碼錶

技術標籤:解壓zip

cc788be32f78627f0f71ecf6c50ac8a5.png

Huffman樹創建出來之後,自然需要用到它的碼錶,碼錶的意思就是通過一串bit能夠找到葉子節點,然後這串bit對應的就是葉子節點Key,Huffman樹每個葉子節點都有一串與之對應的bit,而且因為Huffman樹的特殊,某一個短的bit串都不可能會是其他長串的字首,比如下面這個碼錶:

bitKey
008
0100
0115
1006
1017
11004
11019
111017
1111018
1111103
11111116

如果想檢視自己建立的Huffman樹的碼錶,只需要寫個簡單的遞迴函式打印出來:

Public Sub PrintOut()    RPrintOut root, ""End SubPrivate Function RPrintOut(n As CNode, str As String)    If n.Weight = 2 Then        Debug.Print str, n.Key                Exit Function    Else        RPrintOut n.Left, str & "0"        RPrintOut n.Right, str & "1"    End IfEnd Function

注意我這裡用來判斷是否是葉子節點的條件If n.Weight = 2 Then,在前面建立的過程介紹過,為了建立方便,每一個初始的節點都設定Weight = 2,然後進行左右子樹的擴充套件,擴充套件的時候節點的Weight-1,只有葉子節點是沒有擴充套件左右子樹的,所以Huffman中只有葉子節點的Weight = 2。

當然這裡也可以去判斷左右子樹是否同時為Nothing。

但我們在解壓資料的時候,是從壓縮資料流中一個一個bit的去讀取的,如果先記錄下碼錶,就需要不停的判斷已讀出的bit串是否出現在碼錶中,需要較多的比較次數。

在Huffman樹這個結構中,完全是沒有那個必要的,需要做的是好好利用Huffman樹:

  • 1、節點n從根節點開始

  • 2、從壓縮資料流中讀取一個bit,如果是0,n指向n.Left,如果是1,n指向n.Right

  • 3、判斷n是否是葉子節點,如果是返回n.Key,否則,重複2-3

邏輯其實挺簡單的,程式碼實現:

'找到葉子節點的Key'從bitIndex位置,逐個讀取cpByte中的Bit,直到葉子節點Function GetLeafKey(cpByte() As Byte, ByRef bitIndex As Long) As Long    Dim bValue As Long    Dim n As CNode    Set n = root        'HuffmanTree裡把葉子節點的Weight設定成了2    Do Until n.Weight = 2        '逐個bit的去h中查詢,到達葉子節點為止        bValue = GetBit(cpByte, bitIndex)        bitIndex = bitIndex + 1        '1的時候右        If bValue Then            Set n = n.Right        Else            Set n = n.Left        End If    Loop        GetLeafKey = n.Key        Set n = NothingEnd Function
3f23dbc378fe8fe44760ce9d1b766553.gif
  • 00ZIP是什麼

  • 01實現的功能

  • 02 壓縮過程

  • 03 解壓準備工作

  • 04 解析ZIP檔案結構

  • 05 Huffman樹

8f2223de9434332e2816764fb466e0ac.png