樹是數(shù)據(jù)結(jié)構(gòu)里面一個很重要的內(nèi)容,它的有向無環(huán)圖的結(jié)構(gòu),很適合用來做數(shù)據(jù)排列及檢索,很多數(shù)據(jù)庫的存儲,都是使用的樹這種數(shù)據(jù)結(jié)構(gòu)來做存儲的。
下面讓我們梳理下樹的幾種分類。鑒于有太多關(guān)于樹的定義文章,本文不會對每種樹給出定義及詳細說明,只會梳理總結(jié),關(guān)于各類樹的定義,可參考其他文獻的定義。
普通二叉樹
樹本身是沒有節(jié)點數(shù)限制的,而二叉樹顧名思義,就是每個節(jié)點最多只有2個子節(jié)點的樹,除此之外,沒有其他的限制。
滿二叉樹跟完全二叉樹
在二叉樹的基礎(chǔ)上,滿二叉樹要求樹的每個層級高度完全相同,且除了葉子節(jié)點,樹上其他每個節(jié)點都必須有2個子節(jié)點。
跟滿二叉樹不同,完全二叉樹在最下層的葉子節(jié)點層可以不滿,但必須是從左到右依次填充葉子節(jié)點,不能跳過。
完全二叉樹的創(chuàng)建思路完全按照廣度優(yōu)先遍歷的方式,從根節(jié)點開始依次創(chuàng)建左右兩個節(jié)點,然后把它的左右節(jié)點依次放到隊列中,之后每次從隊列中拿出一個元素,創(chuàng)建左右節(jié)點,并同時放入隊列,如此反復(fù)。
二叉查找樹(BST樹)
二叉查找樹是一種搜索樹,在普通二叉樹的基礎(chǔ)上,增加了數(shù)據(jù)比對的過程,從根節(jié)點開始往下比對,比當(dāng)前節(jié)點數(shù)據(jù)小的,放左邊,大的放右邊。
一般來說,二叉查找樹的查找時間復(fù)雜度是O(Log2 n),但是在極端情況下,數(shù)據(jù)會倒向一側(cè),導(dǎo)致查找的性能極差,變成遍歷查找,也就是O(n)。
平衡二叉樹(AVL樹)
平衡二叉樹在二叉查找樹的基礎(chǔ)上添加了數(shù)據(jù)的平衡過程,它要求每一個節(jié)點,它的左子樹跟右字數(shù)的高度差最多為1層,當(dāng)節(jié)點的變化不符合這個條件時,需要通過從本節(jié)點開始,對樹進行左旋或者右旋調(diào)整,然后逐層往上遞歸,判斷其父節(jié)點是否需要左旋或者右旋,直到整棵平衡二叉樹重新恢復(fù)平衡。
基于上述過程,二叉查找樹存在的問題通過構(gòu)建平衡二叉樹能夠得以解決。
平衡二叉樹在增刪改的過程中增加了一些平衡的消耗,從而達到樹的穩(wěn)定結(jié)構(gòu),這對于以增刪改為主的業(yè)務(wù)場景而言是不合適的,更適合讀多寫少的場景。
紅黑樹
前面幾種樹課本上基本都深入學(xué)習(xí)過,但是紅黑樹可能大部分人都聽過,但是卻沒有深入去學(xué)習(xí)了解。
紅黑樹的性質(zhì):
1、節(jié)點是紅色或黑色。
2、根節(jié)點是黑色。
3、每個紅色節(jié)點的兩個子節(jié)點都是黑色。(從每個葉子到根的所有路徑上不能有兩個連續(xù)的紅色節(jié)點)
4、從任一節(jié)點到其每個葉子的所有路徑都包含相同數(shù)目的黑色節(jié)點。
紅黑樹的算法過程跟平衡二叉樹類似,也是先在對應(yīng)的子節(jié)點插入黑色節(jié)點數(shù)據(jù),然后逐層往上遞歸判斷是否符合紅黑樹的性質(zhì),不符合就左旋或者右旋,但由于它跟平衡二叉樹相比:
- 1、紅黑樹沒有那樣嚴格要求各個節(jié)點的高度差在1度以內(nèi),因此它重新旋轉(zhuǎn)平衡過程的性能代價比平衡二叉樹小,紅黑樹插入過程最多需要重新平衡旋轉(zhuǎn)3次,而平衡二叉樹不一定。
- 2、紅黑樹的高度也可能平衡二叉樹更高。但這是可以接受的一種折中方案,畢竟相比極端的二叉查找樹,紅黑樹的穩(wěn)定性還是非常高的,也是 O(Log2 n)。
鑒于平衡二叉樹的要求嚴格,因此紅黑樹實際上應(yīng)用場景是遠廣于平衡二叉樹的。而由于這兩種樹的旋轉(zhuǎn)需求,因此它們更適合在內(nèi)存的場景使用,比如java的TreeMap。
平衡二叉樹跟紅黑樹的算法時間復(fù)雜度都是O(Log2 n)。
哈夫曼樹
哈夫曼樹是一種帶權(quán)重的,路徑長度最短的最優(yōu)二叉樹。
哈夫曼樹的定義是:
假設(shè)有n個權(quán)值,則構(gòu)造出的哈夫曼樹有n個葉子結(jié)點。 n個權(quán)值分別設(shè)為 w1、w2、…、wn,則哈夫曼樹的構(gòu)造規(guī)則為:
(1) 將w1、w2、…,wn看成是有n 棵樹的森林(每棵樹僅有一個結(jié)點);
(2) 在森林中選出兩個根結(jié)點的權(quán)值最小的樹合并,作為一棵新樹的左、右子樹,且新樹的根結(jié)點權(quán)值為其左、右子樹根結(jié)點權(quán)值之和;
(3) 從森林中刪除選取的兩棵樹,并將新樹加入森林;
(4) 重復(fù)(2)、(3)步,直到森林中只剩一棵樹為止,該樹即為所求得的哈夫曼樹。
下面讓我們看一顆哈夫曼樹的構(gòu)成。
對于排序后的集合是:2,5,6,8,13,19,25,36 的內(nèi)容,每次從集合中取出最小的兩個數(shù),從葉子節(jié)點開始構(gòu)建,組成一個包含兩個節(jié)點以及父節(jié)點的樹(父節(jié)點的值是兩個數(shù)的相加和),再把父節(jié)點放入集合中,重新執(zhí)行構(gòu)建過程,整個過程集合的變化情況是:
2,5,6,8,13,19,25,36 ->
7(2+5),6,8,13,19,25,36 ->
8,13(6+7),13,19,25,36 ->
13,19,21(8+13),25,36 ->
下一輪的時候,由于拿出來的13跟19都小于21,因此無法加入21所在的樹因此結(jié)果是:
21(8+13),25,32(13+19),36 ->
32(13+19),36,46(21+25) ->
46(21+25),32(32+36) ->
114
最終結(jié)果是:
哈夫曼編碼
哈夫曼樹對數(shù)據(jù)集進行編碼的結(jié)果叫做哈夫曼編碼。由于哈夫曼樹帶權(quán)路徑最短的特點,哈夫曼編碼的特點也是對數(shù)據(jù)重新編排,使得整個用哈夫曼編碼組成的內(nèi)容最短。
對上述結(jié)果進行哈夫曼編碼的話,是這樣的一個過程:
從而得出最終編碼結(jié)果,各葉子節(jié)點從左到右分別是:
8 :000
6:0010
2 :00110
5:00111
25:01
13:100
19:101
36:11
總結(jié)
本文介紹了二叉樹的幾種常見的類型,包括普通二叉樹、滿二叉樹、完全二叉樹、二叉查找樹、平衡二叉樹、紅黑樹及哈夫曼樹。
其中:
- 普通二叉樹、滿二叉樹、完全二叉樹是帶有一定基本限制條件的二叉樹,更多作為定義存在,實際上直接使用這些樹的應(yīng)用場景較少。
- 二叉查找樹是一種最簡單的能用于索引的樹結(jié)構(gòu),但是性能不穩(wěn)定。
- 平衡二叉樹跟紅黑樹是為了讓二叉查找樹的性能穩(wěn)定而設(shè)計的樹,其中,平衡二叉樹限制較多,而紅黑樹在其基礎(chǔ)上做了靈活的變通,使其旋轉(zhuǎn)的代價較小,同時性能又比較穩(wěn)定,在工程實踐中更加適合。
- 哈夫曼樹是一種加權(quán)的二叉查找樹,它的生成特點使其非常適合于對內(nèi)容作編碼優(yōu)化。