關於樹的最全知識就在這裏了

前言

今天和大家來說說樹,大家一下子就想到了原始森林、保護樹木、濫砍濫發等關鍵字,不不不。。。我想說的是一種數據結構,廢話不多說,上圖你就知道了

正文

看了上面的圖終於豁然開朗,就是這些東西搞的腦子昏昏漲漲的,動不動就要我手撕紅黑樹,反正我這種老年人是撕不出來了,但是原理還是需要說一說的。下面開始進入正文,什麼???還沒有進入正文,你TM在逗我。。。

數據結構按照邏輯來分類是集合、線性結構、樹形結構、圖形結構,但是爲什麼會有樹形結構的產生呢,網上有一句經典的話可以解釋,那就是爲了彌補其他數據結構的不足,沒毛病,真的沒毛病哈。。。

那麼傳統的集合到底有什麼問題呢,Java中都知道數組查詢效率高,鏈表的插入刪除效率高,那麼有沒有一種數據結構能完美的擁有較高的查詢效率和插入刪除效率呢,這個時候樹就是一種比較好的選擇了,樹分爲二叉樹和多路查找樹。

二叉樹在使用中非常常見,就是最多有兩個葉子節點的樹,這裏有一種特殊情況就是假如沒有左子樹或者右子樹

怎麼樣,看着是不是跟鏈表一模一樣,我們叫他左斜樹或右斜樹,如果二叉樹中所有非葉子結點的度都是2,且葉子結點都在同一層次上,就是滿二叉樹,如果一個二叉樹與滿二叉樹前m個節點的結構相同,這樣的二叉樹被稱爲完全二叉樹。重點來了

二叉查找樹(BST)

  • 若任意節點的左子樹不空,則左子樹上所有節點的值均小於它的根節點的值;
  • 若任意節點的右子樹不空,則右子樹上所有節點的值均大於它的根節點的值;
  • 任意節點的左、右子樹也分別爲二叉查找樹;
  • 沒有鍵值相等的節點。

說到這裏我們開始說下這種樹的插入,如上所述,就是正常的插入就行,是不是很驚喜

數據有了,然後前序遍歷、中序遍歷、後序遍歷,最大值、最小值、前驅後繼、刪除、銷燬瞭解一下,說到這裏難道記憶中算法題中沒有讓你中序遍歷排序後操作的麼???這其中前驅後繼稍微說下,找一個節點前驅的時候有三種情況,後繼同理:

  • 如果節點存在左孩子,那前驅就是左孩子爲根子樹的最大節點
  • 沒有左孩子,節點是一個右孩子,那前驅就是父節點
  • 沒有左孩子,節點是一個左孩子,查找該節點的最低父節點並且父節點有右孩子,那前驅就這個最低父節點

但是二叉搜索樹有一些很極端的情況會導致層級很多,查詢效率低,爲了解決這個問題平衡二叉樹(AVL)出現了,他的不同點就是左右兩個子樹的高度差的絕對值不超過1,這樣我們的查詢效率就有了保證,但是帶來了另外一個問題就是在插入的時候會破壞平衡二叉樹的結構,這個時候就要通過旋轉來解決這個問題,所以其實在插入的時候效率會變低的。需要旋轉的情況分爲四類:

  1. LL: LeftLeft,也稱爲"左左"。插入或刪除一個節點後,根節點的左子樹的左子樹還有非空子節點,導致"根的左子樹的高度"比"根的右子樹的高度"大2,導致AVL樹失去了平衡。
  2.  LR: LeftRight,也稱爲"左右"。插入或刪除一個節點後,根節點的左子樹的右子樹還有非空子節點,導致"根的左子樹的高度"比"根的右子樹的高度"大2,導致AVL樹失去了平衡。
  3.  RL: RightLeft,稱爲"右左"。插入或刪除一個節點後,根節點的右子樹的左子樹還有非空子節點,導致"根的右子樹的高度"比"根的左子樹的高度"大2,導致AVL樹失去了平衡。
  4.  RR: RightRight,稱爲"右右"。插入或刪除一個節點後,根節點的右子樹的右子樹還有非空子節點,導致"根的右子樹的高度"比"根的左子樹的高度"大2,導致AVL樹失去了平衡。

上面的四類,每個類型都有兩種情況,會有左右兩個節點的可能,所以總共是八中情況。其中LL、RR只需要旋轉一次就能恢復平衡二叉樹,LR、RL需要旋轉兩次。由於這種旋轉嚴重的影響了插入的效率,所以紅黑樹誕生了

  • 每個節點顏色不是黑色,就是紅色
  • 根節點是黑色的
  • 如果一個節點是紅色,那麼它的兩個子節點就是黑色的(沒有連續的紅節點)
  • 對於每個節點,從該節點到其後代葉節點的簡單路徑上,均包含相同數目的黑色節點

相對於平衡二叉樹,紅黑樹旋轉情況少一點,雖然AVL樹的時間複雜度雖然優於紅黑樹,但是對於現在的計算機,cpu太快,可以忽略性能差異,所以總體上紅黑樹整體性能略優於AVL樹。如果想看紅黑樹的具體插入過程可以看下HashMap源碼解析(JDK1.8)

這也是爲什麼JDK1.8之後hashMap改成數組+鏈表+紅黑樹的原因。對於哈夫曼樹,又稱最優二叉樹, 是一種帶權路徑長度最短的二叉樹。大家有興趣自行研究下。

說完了二叉樹,接下來說下多路複用樹,B樹,是一種自平衡的樹,其實也是一個二叉樹,但是這種數據結構能夠讓查找數據、順序訪問、插入數據及刪除的動作,都在對數時間內完成。適用於讀寫相對大的數據塊的存儲系統,例如磁盤。還有B+樹,大家一聽肯定不會陌生,Mysql中主鍵索引,也是面試常問的。動不動就要問你爲啥主鍵索引要用B+樹,真是一臉懵逼,想說一句,TM以前就是這樣用的,我怎麼知道。。。

不慌,看這裏,在B樹基礎上,爲葉子結點增加鏈表指針(B樹+葉子有序鏈表),所有關鍵字都在葉子結點中出現,非葉子結點作爲葉子結點的索引;B+樹總是到葉子結點才命中。b+樹的非葉子節點不保存數據,只保存子樹的臨界值(最大或者最小),所以同樣大小的節點,b+樹相對於b樹能夠有更多的分支,使得這棵樹更加矮胖,查詢時做的IO操作次數也更少,所以查詢效率更高,是不是很完美。B+ 樹的特點是能夠保持數據穩定有序,其插入與修改擁有較穩定的對數時間複雜度。適用於關係型數據庫(如Mysql)和操作系統的文件系統中。

R樹是用來做空間數據存儲的樹狀數據結構。例如給地理位置,矩形和多邊形這類多維數據建立索引。大家有興趣自己看下吧。

後記

終於又是洋洋灑灑好多字,然後在不知不覺中就結束了,終於個人的公衆號也開通了,大家有興趣可以關注一波!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章