普通树与二叉树的相互转化及哈夫曼树的了解
普通樹與二叉樹的相互轉化及哈夫曼樹的了解
二叉樹與普通樹的轉化
二叉樹的種種特性使得它更便于處理,如果能將普通樹轉化成二叉樹就好了。
普通樹 -> 二叉樹
回憶孩子兄弟表示法,有第一孩子域(左孩子),還有左孩子的兄弟域。孩子表示法表示的樹很容易轉化成二叉樹,所以只需把樹先轉為孩子兄弟表示法的樣子,再調整層次結構就可以得到二叉樹。
- 加線。在所有兄弟結點之間加一條線。
- 去線。只保留父結點與第一個孩子(左孩子)的連線,與其他孩子的連線刪掉。
- 調整層次,結點的左孩子依然為左孩子,左孩子的兄弟全變成了結點右孩子。
森林也可以轉化成二叉樹,所謂森林就是樹的集合。
- 把森林的每一棵樹轉成二叉樹
- 以某一棵樹作為起始樹,下一棵樹的根結點作為右孩子連接到上一課樹的根結點。直到處理完最后一棵樹。
二叉樹 -> 普通樹
- 加線。如果某個結點存在左孩子,則將左孩子的右結點,其右結點的右孩子...也就是一直深入到沒有右孩子,將這些結點與父結點連線。
- 去線。刪除所有結點與其右孩子的連線。
- 調整結構,讓原本某結點的右孩子與該結點處于一個水平線,則他們成為了兄弟。
二叉樹也能變成森林。
從根結點開始,如果存在右孩子,斷開與右孩子的連線。接著處理上分離后的二叉樹的根結點,如果存在右孩子,斷開連線....如此反復,直到某結點無右孩子。然后將得到的若干二叉樹轉為普通樹。
哈夫曼樹與哈夫曼編碼
哈夫曼編碼用在數據壓縮領域。我們先來看哈夫曼樹。
哈夫曼樹的構造
樹中一個結點到另一個結點之間的分支構成了路徑,路徑上分支的數目稱為路徑長度。樹的路徑長度就是:根結點到每一個結點的路徑長度之和。再把一棵二叉樹的葉子結點帶上權值,定義結點的帶權路徑長度為:根結點到葉子結點的路徑長度 * 葉子結點的權值。那么樹的帶權路徑長度為所有葉子結點的帶權路徑長度之和。
比如有結點數為n的二叉樹,有m個葉子結點。權值分別是w1, w2, w3...根結點到它們的路徑長度分別是m1, m2, m3...則m1*w1 + m2*w2 + m3*w3 +...+ mm*wm就是這棵樹的帶權路徑長度。
比如二叉樹a,結點A的路徑長度為1,結點D的路徑長度為4...于是該樹的帶權路徑長度就是:5*1 + 15*2 +40*3 +30*4 + 10*4 = 315
二叉樹b的帶權路徑長度為:40*2 + 5*3 + 15*3 +30*2 + 10*2 = 220
由于n個結點的二叉樹有多種可能的形態,葉子結點的個數、結點的路徑長度都各不相同,這些樹的帶權路徑長度有的很大有的很小。我們的目的是要找出使樹的帶權路徑長度最小的二叉樹,這樣的二叉樹稱為哈夫曼樹。哈夫曼樹的形態也不唯一(比如某棵哈夫曼樹作鏡面對稱),但是這些樹帶權路徑長度一定是唯一值。
上圖就是一棵哈夫曼樹,它的帶權路徑長度為40*1 + 30*2 + 15*3 + 5*4 + 10*4 = 205,比前面兩種情況的值都小。那么這棵樹是怎么來的呢?幸好有簡單的構造方法。
- 先將帶權的葉子結點按照權值從小到大排序,以上圖為例子就是{A: 5, E: 10, B: 15, D: 30, C: 40}
- 取出前兩個結點,新增一個N1結點作為這兩個結點的父結點,權值小的作為N1的左孩子,權值稍大的作為右孩子,并將N1的權值為設置為這兩個結點的權值之和,如圖N1的權值為A和E的權值之和15。
- 已取出的葉子結點從序列中刪除,并將新增的N1結點插入到序列中合適的位置,保持序列有序。然后重復上一步驟。直到所有葉子的結點的都已被取出,至此就完成了哈夫曼樹的構造。(完成的圖就是上圖那樣)
哈夫曼編碼
試想將一段字符通過網絡傳輸給別人,如BADCADFEED,由于其中只有ABCDEF六個字母,用三位的二進制數就可以完全表示。每個字母被編碼成以下表格所示。
| 二進制編碼 | 000 | 001 | 010 | 011 | 100 | 101 |
這樣上面的BADCADFEED編碼后就是001000011010000011101100100011,長度是30。對方接收到這一長串再根據上表,每三位代表一個字母,解碼出真正的序列。
現在我們嘗試用哈夫曼編碼對這段數據進行壓縮。假如我們有一段字符要進行傳輸,這段字符中共出現6個字母,每個字母出現的頻率是{A: 27, B: 8, C: 15, D: 15, E: 30, F: 5}。根據上面介紹的哈夫曼樹的構造,可以得到下面的左圖。
現在將結點到左孩子的路徑權值改為0,到右孩子的權值改為1,從根結點到葉子結點所經過的路徑組成的0、1序列就是該字符的編碼。舉比如字符D被編碼為00,可以列出每個字符的編碼序列。
| 二進制編碼 | 01 | 1001 | 101 | 00 | 11 | 1000 |
可以看出二進制位數參差不齊了,頻率高的二進制位數少,頻率低的所需位數就多。BADCADFEED現在被編碼成了1001010010101001000111100,長度是25。比上面少了5個字符,這說明我們可以用更少的數據量傳輸內容,卻不丟失語意。我們確實成功壓縮了數據。
對方接收到這一長串,再根據上表解碼出真正的序列。不過在解碼的時候,由于表中的編碼各個字符的二進制位數不是固定,有的3位數、有的4位數....如果某個編碼序列是另外一個編碼序列的前綴,在解碼的時候我們就不能確定這到底是哪個字符。所以在編碼的時候一定要避免這樣的情況發生,編碼方案需要滿足:任意字符的編碼都不是其他任意字符編碼的前綴,這種編碼稱為前綴編碼。
by @sunhaiyu
2017.9.14
轉載于:https://www.cnblogs.com/sun-haiyu/p/7521466.html
總結
以上是生活随笔為你收集整理的普通树与二叉树的相互转化及哈夫曼树的了解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: uniapp引入阿里巴巴矢量图标库
- 下一篇: bjui简单了解