霍夫曼樹
霍夫曼樹 是由美國電腦科學家大衛·霍夫曼(David Albert Huffman)(又譯為哈夫曼、赫夫曼)在1952年發明霍夫曼編碼所用到的特殊二叉樹。為了紀念他的成就,於是就叫 霍夫曼樹,他的編碼方法稱為 霍夫曼編碼。
從二叉樹中一個節點到另一個節點之間的分支構成兩個節點之間的路徑,路徑上的分支數目稱做路徑長度。樹的路徑長度就是從樹根到每一節點的路徑長度之和。
在帶有權重的節點中,節點帶權的路徑長度是從該節點到樹根之間的路徑長度與節點上權的乘積。樹的帶權路徑長度是樹中所有葉子節點的帶權路徑長度之和。其中帶權路徑長度最小的二叉樹稱做 霍夫曼樹,也稱為 最優二叉樹。
構建霍夫曼樹
1.先把有權值的葉子節點按照從小到大的順序排列成一個有序序列。
2.取前兩個最小權值的節點作為一個新節點(T1)的兩個子節點,注意相對較小的是左節點,稍大點的是右節點。
3.把 T1 2個子節點的和,加入到剩餘有序序列中,按第二步的規則構建新的節點。
4.重複第三步,直到連上所有節點為止。這棵樹便是 霍夫曼樹。
霍夫曼編碼
按照需要編碼的字符集的權值來構造一棵 霍夫曼樹。規定霍夫曼樹的左分支代表 0,右分支代表 1,則從根節點到葉子節點所經過的路徑分支組成的0和1的序列便為該結點對應字元的編碼,這就是 赫夫曼編碼。
比如現在有一段內容“ACBDEDABDA”需要傳輸。假設一個字母佔 3 位,A=000,B=001,C=010,D=011,E=100。那麼這段內容的編碼是 000010001011100011000001011000(佔 30 位)。
假設 ABCDE 的權重分別為 32,20,10,30,8。那麼構建好霍夫曼樹後 A=11,B=01,C=001,D=10,E=000。霍夫曼樹編碼內容是 1100101100001011011011(佔 22 位)。
構建好的霍夫曼樹
根據霍夫曼樹轉換的編碼 根據上面例子,用霍夫曼編碼,節省了 8 位。說明資料被壓縮了,節約了大約 27% 的儲存或傳輸成本。隨著字元的增加和多字元權重的不同,這種壓縮會更加顯出其優勢。編碼中非0即1,長短不等的話其實是很容易混淆的,所以若要設計長短不等的編碼,則必須是任一字元的編碼都不是另一個字元的編碼的字首,這種編碼稱做字首編碼。
在解碼時,還是要用到霍夫曼樹,即傳送方和接收方必須要約定好同樣的霍夫曼編碼規則。
總結
霍夫曼樹 是根據權重來構建的二叉樹,我們也稱為 最優二叉樹。
它的主要作用是用來編碼,也可以用來壓縮資料。也可用來編碼之後傳送給第三方,提升安全性和節省網路資源,然後在根據雙方約定好的 霍夫曼樹 進行解碼,可以做到無損編碼和無錯解碼。
PS:
清山綠水始於塵,博學多識貴於勤。
我有酒,你有故事嗎?
微信公眾號:「清塵閒聊」。
歡迎一起談天說地,聊程式碼。