1. 程式人生 > 實用技巧 >紅黑樹的前身--2-3平衡樹

紅黑樹的前身--2-3平衡樹

什麼是2-3樹

為什麼要使用樹

  • 描述 1 - 多,N-M、層次等關係
  • 從最根本的原因來看,使用樹結構是為了提升整體的效率:插入、刪除、查詢(索引),尤其是索引操作。因為相比於連結串列,一個平衡樹的索引時間複雜度是 O ( l o g n ) O(log_n) O(logn), 而陣列的索引時間複雜度是 O ( n ) O(n) O(n)
    在這裡插入圖片描述
  • 例子:資料庫索引、檔案索引等一般都是用樹形結構儲存的

從BST談起

我們學的第一個樹結果一般都是二叉查詢樹(BST)

特點:右子節點的資料要比根節點的大,左子節點的資料比根節點小,特殊情況下會變成一個連結串列。

二叉搜尋樹其期望高度(即為一棵平衡樹時)為log2n,其各操作的時間複雜度(O(log2n))同時也由此而決定。但是,如果插入節點時,插入元素序列本身就是有序的,那麼BST樹就退化成一個線性表了,操作的時間複雜度為O(n), 之所以會變成O(n),是因為樹的高度變大了,BST的比較次數最大是等於樹的高度的

。因此,如果想要減少比較次數,就需要降低樹的高度。
在這裡插入圖片描述

為了解決上面的問題,我們引入了二叉搜尋樹

avl樹的引入

構建二叉查詢樹時,當插入或者刪除資料的時候,可能造成樹的不平衡, 這個時候,我們可以通過旋轉節點來調整樹的高度,使得每個節點的左右兩個子樹的高度差的決定之不超過1(為什麼要讓高度差不超過1?這樣才能保證整棵樹的深度最小),這樣的樹叫做平衡二叉查詢樹(Self-balancing binary search tree)

平衡二叉搜尋樹又被稱為AVL樹(有別於AVL演算法),且具有以下性質:它是一 棵空樹或它的左右兩個子樹的高度差的絕對值不超過1,並且左右兩個子樹都是一棵平衡二叉樹。

在平衡二叉搜尋樹中,我們可以看到,其高度一般都良好地維持在O(log(n)),大大降低了操作的時間複雜度。

在這裡插入圖片描述
在二叉樹的查詢節點少的情況下,二叉樹的操作效率較高,但是如果 二叉 樹的節點很多 ( 比如 1 億 ) , 就存在如下問題

  • 二叉樹需要載入到記憶體的, 在構建二叉樹時,需要多次進行 i/o 操作 ( 海量資料存在資料庫或檔案中 ) 【資料一般儲存在磁碟中,處理在記憶體中,記憶體比磁碟快的多,但是也貴得多。像TB級別的資料庫不可能全部讀出來放到記憶體中去,太過昂貴,而且也沒必要,大部分資料是不經常用的】
  • 節點海量, 也 會造成二叉樹的高度很大,會降低操作 速 度
  • 由於每次插入或刪除節點後,都可能會破壞AVL的平衡,而要動態保證AVL的平衡需要很多操作,這些操作會影響整個資料結構的效能,除非是在樹的結構變化特別少的情形下,否則AVL樹平衡帶來的搜尋效能提升有可能還不足為了平衡樹所帶來的效能損耗,在一些標準的集合框架中,AVL樹應用得還是比較少的,因為綜合為了平衡的效能損耗和平衡後搜尋帶來的效能提升,對整個資料結構的效能提高不多。

其實不是的,實際上2-3樹的查詢時間複雜度也是為 O(logN) ,而出現這種多路查詢樹,

為了解決 上面的問題,我們引入了多叉樹

平衡二叉樹的常用實現方法有紅黑樹、AVL、替罪羊樹、Treap、伸展樹等。 最小二叉平衡樹的節點總數的公式如下 F(n)=F(n-1)+F(n-2)+1 這個類似於一個遞迴的數列,可以參考Fibonacci(斐波那契)數列,1是根節點,F(n-1)是左子樹的節點數量,F(n-2)是右子樹的節點數量。??? ???

多叉樹

在二叉樹中,一個節點只能儲存一個數據項,最多有兩個子節點。在大資料量的情況下,樹肯定會很高,此時查個數據對磁碟讀個幾千上萬次那肯定是不行的。所以我們可以通過在一個節點中存放更多的資料項和引用更多的子節點,這樣,樹不用很高就可以標識很大的資料量了,檢索次數就大大減少了,用這種資料結構去磁碟中存取資料,磁碟IO次數的次數也會很少。

B樹

2-3樹

2-3樹是最簡單的B樹結構, 其每個非葉節點都有兩個或三個子女,而且所有葉都在統一層上。

具有如下特點:

  • 滿足二分搜尋樹的基本性質
  • 2-3 樹的所有葉子節點都在同一層 .( 只要是 B 樹都滿足這個條件 )
  • 節點可以存放1個元素,或者2個元素
    • 2結點: 存放1個元素的結點要麼有2個子結點,要麼沒有子節點(葉子節點)
    • 3結點:存放2個元素的結點要麼有3個子結點,要麼沒有子節點(葉子節點)

在這裡插入圖片描述

  • 每個節點的key從左到右保持了從小到大的順序,兩個key之間的子樹中所有的key一定大於它的父節點的左key,小於父節點的右key
  • 2-3樹是一顆絕對平衡的樹: 從根節點到任意葉子節點所經過的節點相同

在這裡插入圖片描述

根據2-3樹的定義,2-3樹也可能會失去平衡,那麼在插入和刪除節點時也是需要動態維持平衡的,但維持平衡的策略和AVL樹是不一樣的。AVL樹是通過旋轉來恢復平衡的,而2-3樹是通過節點分裂來維持的,因為2-3樹中有一些2節點,這些2節點可以變成3節點來容納插入節點,最後導致插入節點而不會讓樹失去平衡。如果2-3樹中已經沒有2節點可以分裂成3節點了呢?其實這種情況下已經可以直接插入節點了,這時候插入的位置不會導致有深度差超過1。

為啥檔案/資料庫索引要用B樹而不用二叉查詢樹

我們已經知道:資料庫索引、檔案索引等一般都是用樹形結構儲存的

  • 為什麼要用樹形結構儲存?

    • 樹形結構比如B樹,B+樹,二叉查詢樹都是有序的,所以查詢效率很高,可以在 O ( l o g n ) O(log_n) O(logn)的時間複雜度查詢到目標資料
  • 索引一般用哪種樹形結構?

    • 大部分B+樹,少部分B樹
  • 為什麼不用雜湊表

    • 雜湊表雖然能夠在 O ( 1 ) O(1) O(1)查詢到目標,但是不能模糊查詢,並且如果雜湊衝突太多,也會導致 Q ( n ) Q(n) Q(n)查詢效率的
  • 為什麼不用二叉查詢樹?


【面試被懟】什麼是B樹?為啥檔案/資料庫索引要用B樹而不用二叉查詢樹?
2-3樹與2-3-4樹

資料結構樹,為什麼是B+樹
一步步分析為什麼B+樹適合作為索引的結構
https://segmentfault.com/a/1190000023652024
笨辦法學資料結構 2-3樹的圖解–完成