啥是二叉搜索樹、B樹、B+樹、AVL樹、紅黑樹,怎麼那麼多的樹,一文全總結

在瞭解 B樹、B+樹、AVL樹、紅黑樹 以前,咱們先看一下各類樹型結構的大體實際應用場景:html

B和B+樹:主要用在文件系統以及數據庫中作索引等

AVL樹:平衡二叉樹之一,應用相對其餘數據結構比較少,windows對進程地址空間的管理用到了AVLmysql

紅黑樹:平衡二叉樹,普遍應用在C++STL中,好比map和set,Java的TreeMapgit

樹結構已經有了不少種形式,爲什麼出現 B樹、B+樹、AVL樹、紅黑樹,首先要了解一下二叉搜索樹github

  1. 二叉搜索樹

1)概念

平衡二叉樹是採用二分法思惟把數據按規則組裝成一個樹形結構的數據,用這個樹形結構的數據減小無關數據的檢索,大大的提高了數據檢索的速度。面試

咱們在二叉樹的深度遍歷過程當中,使用中序遍歷,就能獲取獲得有序的序列。算法

2)特色

  • 任意節點左子樹不爲空,則左子樹的值均小於根節點的值.
  • 任意節點右子樹不爲空,則右子樹的值均大於於根節點的值.
  • 任意節點的左右子樹也分別是二叉查找樹.
  • 沒有鍵值相等的節點.

3)二叉搜索樹存在的侷限

這裏寫圖片描述

二叉樹在查找數據時,時間複雜度最好狀況是O(logn) ,最壞狀況下時間複雜度O(n),如a圖所示,二叉樹退化成一個鏈表了,剛好選擇了最小或者最大的節點作root,節點排在了一條直線上。sql

所以,在二叉查找樹的基礎上,又出現了AVL樹,紅黑樹,它們兩個都是基於二叉查找樹,只是在二叉查找樹的基礎上又對其作了限制.數據庫

  1. B樹

1)概念

B樹又名平衡多路查找樹(查找路徑不僅兩個),不一樣於常見的二叉樹,它是一種多叉樹,咱們常見的使用場景通常是在數據庫索引技術裏,大量使用者B樹和B+樹的數據結構。windows

有些教材中,也把B樹稱爲B-樹, -只是一個符號,無需太在乎命名形式。緩存

這裏寫圖片描述

B樹大多用在磁盤上用於查找磁盤的地址。由於磁盤會有大量的數據,有可能沒有辦法一次將須要的全部數據加入到內存中,因此只能逐一加載磁盤頁,每一個磁盤頁就對應一個節點,而對於B樹來講,B樹很好的將樹的高度下降了,這樣就會減小IO查詢次數,雖然一次加載到內存的數據變多了,但速度絕對快於AVL或是紅黑樹的。

2)特色

1)定義任意非葉子結點最多隻有M個兒子;且M>2
2)全部節點關鍵字是按遞增次序排列,並遵循左小右大原則
3)位於M-1和M key的子節點的值位於M-1 和M key對應的Value之間
4)其它節點至少有M/2個子節點 [M/2,M-1]
5)全部葉子節點都在同一層

3)B樹查詢流程

這裏使用字母來表示:

如上圖我要從上圖中找到E字母,查找流程以下:

(1)獲取根節點的關鍵字進行比較,當前根節點關鍵字爲M,E<M(26個字母順序),因此往找到指向左邊的子節點(二分法規則,左小右大,左邊放小於當前節點值的子節點、右邊放大於當前節點值的子節點);

(2)拿到關鍵字D和G,D<E<G 因此直接找到D和G中間的節點;

(3)拿到E和F,由於E=E 因此直接返回關鍵字和指針信息(若是樹結構裏面沒有包含所要查找的節點則返回null);

搜索B樹時,很明顯,訪問節點(即讀取磁盤)的次數與樹的高度呈正比,而B樹與紅黑樹和普通的二叉查找樹相比,雖然高度都是對數數量級,可是顯然B樹中log函數的底能夠比2更大,所以,和二叉樹相比,極大地減小了磁盤讀取的次數。

3.B+樹

1)概念

B+樹時B樹的一種升級版本,B+樹查找的效率要比B樹更高、更穩定。

B+樹是應文件系統所需而產生的一種B樹的變形樹(文件的目錄一級一級索引,只有最底層的葉子節點(文件)保存數據.),非葉子節點只保存索引,不保存實際的數據,數據都保存在葉子節點中.

這不就是文件系統文件的查找嗎?咱們就舉個文件查找的例子:有3個文件夾,a,b,c, a包含b,b包含c,一個文件yang.c, a,b,c就是索引(存儲在非葉子節點), a,b,c只是要找到的yang.c的key,而實際的數據yang.c存儲在葉子節點上.
全部的非葉子節點均可以當作索引部分

這裏寫圖片描述

2)特色

B+樹和B樹相似,但多了幾條規則

  • 非葉子結點的子樹指針個數與關鍵字(節點中的元素個數)個數相同
  • 非葉子結點的子樹指針P[i],指向關鍵字值屬於[K[i], K[i+1])的子樹(B-樹是開區間)
  • 全部葉子結點有一個鏈指針
  • 全部關鍵字都在葉子結點出現
  • 只有葉子節點有Data域

3)B+樹與B樹對比

一、B+樹的層級更少:相較於B樹,B+每一個非葉子節點存儲的關鍵字數更多,樹的層級更少因此查詢數據更快;

二、B+樹查詢速度更穩定:B+全部關鍵字數據地址都存在葉子節點上,因此每次查找的次數都相同因此查詢速度要比B樹更穩定;

三、B+樹自然具有排序功能:B+樹全部的葉子節點數據構成了一個有序鏈表,在查詢大小區間的數據時候更方便,數據緊密性很高,緩存的命中率也會比B樹高。

四、B+樹全節點遍歷更快:B+樹遍歷整棵樹只須要遍歷全部的葉子節點便可,,而不須要像B樹同樣須要對每一層進行遍歷,這有利於數據庫作全表掃描。

B樹相對於B+樹的優勢是,若是常常訪問的數據離根節點很近,而B樹非葉子節點自己存有關鍵字其數據的地址,因此這種數據檢索的時候會要比B+樹快。

B+樹相對於B樹的最主要的優勢:

  1. B+樹只有葉子節點存放數據,而其餘節點只存放索引,而B樹每一個節點都有Data域。因此相同大小的節點B+樹包含的索引比B樹的索引更多(由於B樹每一個節點還有Data域)
  2. B+樹的葉子節點是經過鏈表鏈接的,因此找到下限後能很快進行區間查詢,比B樹中序遍歷快
  1. AVL樹(平衡二叉樹)

1)概念

AVL、紅黑樹是對二叉搜索樹的改進版本。

平衡因子:節點的左右子樹深度之差。在一棵平衡二叉樹中,節點的平衡因子只能取 0 、1 或者 -1 ,分別對應着左右子樹等高,左子樹比較高,右子樹比較高。

AVL樹是帶有平衡條件的二叉查找樹,通常是用平衡因子差值判斷是否平衡並經過旋轉來實現平衡,左右子樹樹高不超過1,和紅黑樹相比,它是嚴格的平衡二叉樹,平衡條件必須知足(全部節點的左右子樹高度差不超過1)。

無論咱們是執行插入仍是刪除操做,只要不知足上面的條件,就要經過旋轉來保持平衡,而旋轉是很是耗時的,由此咱們能夠知道AVL樹適合用於插入刪除次數比較少,但查找多的狀況。

這裏寫圖片描述

由上圖所知:任意節點的左右子樹的平衡因子差值都不會大於1

2)AVL保持平衡的四種操做

增刪改查操做和二分搜索樹相似,可是要多考慮的就是對節點的平衡考慮,若是一串數字的插入順序爲3,4,5。那麼這棵樹結構就會退化爲一個鏈表。而這時候AVL就會對這個樹進行旋轉操做來達到平衡,因此,咱們就知道旋轉的操做會在增長,刪除,修改這三個地方進行旋轉。旋轉操做分爲下面四種狀況

1. LL右單旋轉

image

如圖,8的左子樹已經退化爲鏈表,而且5,8這兩個節點再也不平衡,這時咱們先找到深度最深的不平衡節點5,對節點5進行LL旋轉操做,在如圖的這種狀況下,獲得右圖的結構

2. RR左單旋轉

image

如圖,當插入順序爲當插入順序爲8,3,10,13,15的時候,樹的結構變成左邊的樣子,這時10節點和8節點已經不平衡,爲了保持AVL的平衡,咱們要對10節點進行RR旋轉,如右圖所示

3. LR先左後右

image

如圖。5,8節點已經不平衡,這時要對5節點作平衡處理,首先將5進行RR左旋轉,7的左節點也變爲5的右節點。

image

這時7,8仍是不平衡的,對8進行右旋轉,8的右節點也變爲8的左節點,如圖。

4. RL先右後左

image

如左圖,8,13節點不平衡,對13節點進行LL右旋轉,獲得右圖

image

這時8,10是不平衡的,對8節點進行RR左旋轉,獲得右圖。

以上就是保持平衡的方式。

3)AVL存在的侷限性

因爲維護這種高度平衡所付出的代價比從中得到的效率收益還大,故而實際的應用很少,

更多的地方是用追求局部而不是很是嚴格總體平衡的紅黑樹.固然,若是應用場景中對插入刪除不頻繁,只是對查找要求較高,那麼AVL仍是較優於紅黑樹.

  1. 紅黑樹

1)概念

一種二叉查找樹,但在每一個節點增長一個存儲位表示節點的顏色,能夠是red或black(非紅即黑)。經過對任何一條從根到葉子的路徑上各個節點着色的方式的限制,紅黑樹確保沒有一條路徑會比其它路徑長出兩倍。它是一種弱平衡二叉樹(因爲是弱平衡,能夠推出,相同的節點狀況下,AVL樹的高度低於紅黑樹),相對於要求嚴格的AVL樹來講,它的旋轉次數少,因此對於搜索、插入、刪除操做較多的狀況下,咱們就用紅黑樹。

這裏寫圖片描述

2)特徵

一、每一個節點非紅即黑;

二、根節點是黑的;

三、每一個葉節點(葉節點即樹尾端NULL指針或NULL節點)都是黑的;

四、若是一個節點是紅的,那麼它的兩兒子都是黑的;

五、對於任意節點而言,其到葉子點樹NULL指針的每條路徑都包含相同數目的黑節點;

六、高度始終保持在h = logn

七、紅黑樹的查找、插入、刪除的時間複雜度最壞爲O(log n)

3)紅黑樹的自平衡操做

但插入、或者刪除紅黑樹的數值時,爲了從新符合紅黑樹的規則,須要對紅黑樹進行旋轉、變色操做。

當在對紅黑樹進行插入和刪除等操做時,對樹作了修改可能會破壞紅黑樹的性質。爲了繼續保持紅黑樹的性質,能夠經過對結點進行從新着色,以及對樹進行相關的旋轉操做,即經過修改樹中某些結點的顏色及指針結構,來達到對紅黑樹進行插入或刪除結點等操做後繼續保持它的性質或平衡的目的。

樹的旋轉分爲左旋和右旋,下面藉助圖來介紹一下左旋和右旋這兩種操做。

  • 左旋:以某個結點做爲支點(旋轉結點),其右子結點變爲旋轉結點的父結點,右子結點的左子結點變爲旋轉結點的右子結點,左子結點保持不變。

 使用動圖更好理解:【由動圖可知,紅黑樹並非簡單的旋轉,須要伴隨着子樹的轉換】

  • 右旋:以某個結點做爲支點(旋轉結點),其左子結點變爲旋轉結點的父結點,左子結點的右子結點變爲旋轉結點的左子結點,右子結點保持不變。

使用動圖更好理解:

 

咱們先忽略顏色,能夠看到旋轉操做不會影響旋轉結點的父結點,父結點以上的結構仍是保持不變的。
左旋隻影響旋轉結點和其右子樹的結構,把右子樹的結點往左子樹挪了。
右旋隻影響旋轉結點和其左子樹的結構,把左子樹的結點往右子樹挪了。

因此旋轉操做是局部的。另外能夠看出旋轉能保持紅黑樹平衡的一些端詳了:當一邊子樹的結點少了,那麼向另一邊子樹「借」一些結點;當一邊子樹的結點多了,那麼向另一邊子樹「租」一些結點。

  • 變色:結點的顏色由紅變黑或由黑變紅。

Java _TreeMap_實現了_SortedMap_接口,也就是說會按照key的大小順序對_Map_中的元素進行排序,key大小的評判能夠經過其自己的天然順序(natural ordering),也能夠經過構造時傳入的比較器(Comparator)。_TreeMap_底層經過紅黑樹(Red-Black tree)實現

看一下紅黑樹插入一個數值,紅黑樹自平衡的一個過程:

TreeMap_put.png

6. 二叉搜索樹、B樹、B+樹、AVL樹、紅黑樹的常見面試題

1)爲何設計紅黑樹

紅黑樹經過它規則的設定,確保了插入和刪除的最壞的時間複雜度是O(log N) 。

紅黑樹解決了AVL平衡二叉樹的維護起來比較麻煩的問題,紅黑樹,讀取略遜於AVL,維護強於AVL,每次插入和刪除的平均旋轉次數應該是遠小於平衡樹。

所以:

相對於要求嚴格的AVL樹來講,紅黑樹的旋轉次數少,因此對於插入、刪除操做較多的狀況下,咱們就用紅黑樹。可是,只是對查找要求較高,那麼AVL仍是較優於紅黑樹.

2)B樹的做用

B樹大多用在磁盤上用於查找磁盤的地址。由於磁盤會有大量的數據,有可能沒有辦法一次將須要的全部數據加入到內存中,因此只能逐一加載磁盤頁,每一個磁盤頁就對應一個節點,而對於B樹來講,B樹很好的將樹的高度下降了,這樣就會減小IO查詢次數,雖然一次加載到內存的數據變多了,但速度絕對快於AVL或是紅黑樹的。

3)B樹和 B+樹的區別

B/B+樹用在磁盤文件組織、數據索引和數據庫索引中。其中B+樹比B 樹更適合實際應用中操做系統的文件索引和數據庫索引,由於:
一、B+樹的磁盤讀寫代價更低
B+樹的內部結點並無指向關鍵字具體信息的指針。所以其內部結點相對B 樹更小。若是把全部同一內部結點的關鍵字存放在同一盤塊中,那麼盤塊所能容納的關鍵字數量也越多。一次性讀入內存中的須要查找的關鍵字也就越多。相對來講IO讀寫次數也就下降了。

舉個例子,假設磁盤中的一個盤塊容納16bytes,而一個關鍵字2bytes,一個關鍵字具體信息指針2bytes。一棵9階B-tree(一個結點最多8個關鍵字)的內部結點須要2個盤快。而B+ 樹內部結點只須要1個盤快。當須要把內部結點讀入內存中的時候,B 樹就比B+ 樹多一次盤塊查找時間(在磁盤中就是盤片旋轉的時間)。

二、B+-tree的查詢效率更加穩定
因爲非終結點並非最終指向文件內容的結點,而只是葉子結點中關鍵字的索引。因此任何關鍵字的查找必須走一條從根結點到葉子結點的路。全部關鍵字查詢的路徑長度相同,致使每個數據的查詢效率至關。

三、B樹在元素遍歷的時候效率較低

因爲B+樹的數據都存儲在葉子結點中,分支結點均爲索引,方便掃庫,只須要掃一遍葉子結點便可,可是B樹由於其分支結點一樣存儲着數據,咱們要找到具體的數據,須要進行一次中序遍歷按序來掃,因此B+樹更加適合在區間查詢的狀況,因此一般B+樹用於數據庫索引。在數據庫中基於範圍的查詢相對頻繁,因此此時B+樹優於B樹。

4)B樹和紅黑樹的區別

最大的區別就是樹的深度較高,在磁盤I/O方面的表現不如B樹。

要獲取磁盤上數據,必須先經過磁盤移動臂移動到數據所在的柱面,而後找到指定盤面,接着旋轉盤面找到數據所在的磁道,最後對數據進行讀寫。磁盤IO代價主要花費在查找所需的柱面上,樹的深度過大會形成磁盤IO頻繁讀寫。根據磁盤查找存取的次數每每由樹的高度所決定。

因此,在大規模數據存儲的時候,紅黑樹每每出現因爲樹的深度過大而形成磁盤IO讀寫過於頻繁,進而致使效率低下。在這方面,B樹表現相對優異,B樹能夠有多個子女,從幾十到上千,能夠下降樹的高度。

5)AVL樹和紅黑樹的區別

紅黑樹的算法時間複雜度和AVL相同,但統計性能比AVL樹更高。

一、紅黑樹和AVL樹都可以以O(log2 n)的時間複雜度進行搜索、插入、刪除操做。
二、因爲設計,紅黑樹的任何不平衡都會在三次旋轉以內解決。AVL樹增長和刪除可能須要經過一次或屢次樹旋轉來從新平衡這個樹。

查找方面:
  紅黑樹的性質(最長路徑長度不超過最短路徑長度的2倍),其查找代價基本維持在O(logN)左右,但在最差狀況下(最長路徑是最短路徑的2倍少1),比AVL要略遜色一點。
  AVL是嚴格平衡的二叉查找樹(平衡因子不超過1)。查找過程當中不會出現最差狀況的單支樹。所以查找效率最好,最壞狀況都是O(logN)數量級的。

因此,綜上:
  AVL比RBtree更加平衡,可是AVL的插入和刪除會帶來大量的旋轉。 因此若是插入和刪除比較多的狀況,應該使用RBtree, 若是查詢操做比較多,應該使用AVL

AVL是一種高度平衡的二叉樹,維護這種高度平衡所付出的代價比從中得到的效率收益還大,故而實際的應用很少,更多的地方是用追求局部而不是很是嚴格總體平衡的紅黑樹。固然,若是場景中對插入刪除不頻繁,只是對查找特別有要求,AVL仍是優於紅黑的。

6)數據庫爲何使用B樹,而不使用AVL或者紅黑樹

咱們假設B+樹一個節點能夠有100個關鍵字,那麼3層的B樹能夠容納大概1000000多個關鍵字(100+101100+101101*100)。而紅黑樹要存儲這麼多至少要20層。因此使用B樹相對於紅黑樹和AVL能夠減小IO操做

7)mysql的Innodb引擎爲何採用的是B+樹的索引方式

B+樹只有葉子節點存放數據,而其餘節點只存放索引,而B樹每一個節點都有Data域。因此相同大小的節點B+樹包含的索引比B樹的索引更多(由於B樹每一個節點還有Data域)

還有就是B+樹的葉子節點是經過鏈表鏈接的,因此找到下限後能很快進行區間查詢,比B樹中序遍歷快

8)紅黑樹 和 b+樹的用途有什麼區別?

  1. 紅黑樹多用在內部排序,即全放在內存中的,STL的map和set的內部實現就是紅黑樹。
  2. B+樹多用於外存上時,B+也被成爲一個磁盤友好的數據結構。

9)爲何B+樹比B樹更爲友好

  • 磁盤讀寫代價更低
    樹的非葉子結點裏面沒有數據,這樣索引比較小,能夠放在一個blcok(或者儘量少的blcok)裏面。避免了樹形結構不斷的向下查找,而後磁盤不停的尋道,讀數據。這樣的設計,能夠下降io的次數。
  • 查詢效率更加穩定
    非終結點並非最終指向文件內容的結點,而只是葉子結點中關鍵字的索引。因此任何關鍵字的查找必須走一條從根結點到葉子結點的路。全部關鍵字查詢的路徑長度相同,致使每個數據的查詢效率至關。
  • 遍歷全部的數據更方便
    B+樹只要遍歷葉子節點就能夠實現整棵樹的遍歷,而其餘的樹形結構 要中序遍歷才能夠訪問全部的數據。

參考:

http://www.javashuo.com/article/p-orraekjs-n.html

https://www.jianshu.com/p/86a1fd2d7406

https://juejin.im/post/6844903859974848520#heading-16

http://www.javashuo.com/article/p-vrluzavz-ez.html

https://marian5211.github.io/2018/03/09/B%E6%A0%91%E3%80%81B-%E6%A0%91%E3%80%81AVL%E6%A0%91%E3%80%81Trie%E6%A0%91%E5%8F%8A%E5%85%B6%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF/


最後的最後,歡迎關注公衆號。。。。。

------------------------  end -------------------------------------

相關文章
相關標籤/搜索