資料結構--2-3樹

零星發表於2019-10-03

2-3 查詢樹(2-3-Search-Tree)

  • 2-結點:標準二叉樹中的結點稱為2-結點(含有一個鍵和兩條連結)。

  • 3-結點:包含兩個鍵和三條連結。

定義:一顆2-3查詢樹或為一棵空樹,或由以下結點組成:

  2-結點,含有一個鍵(及其對應的值)和兩條連結,左連結指向的2-3樹中的鍵都小於該結點,右連結指向的2-3樹中的鍵都大於該結點。

  3-結點,含有兩個鍵(及其對應的值)和三條連結,左連結指向的2-3樹中的鍵都小於該結點,中連結指向的2-3樹中的鍵都位於該結點的 兩個鍵之間,右連結指向的2-3樹中的鍵都大於該結點。

資料結構--2-3樹

2-3 查詢樹(2-3-Search-Tree) 的操作

一棵完美平衡的2-3查詢樹中所有空連結到根節點的距離應該都是相同的。

查詢

  2-3 查詢樹中的查詢與二分搜尋樹的查詢類似。要判斷一個鍵是否在樹中,先將它和根結點中的鍵比較。如果它和其中任意一個 相等,查詢命中。否則,根據比較的結果找到指向相應區間的連結,並在其指向的子樹中遞迴繼續查詢。如果是個空連結,查詢未命中。

在如上圖所示的2-3樹中查詢鍵為2的結點是否存在,過程如下:

資料結構--2-3樹

在如上圖所示的2-3樹中查詢鍵為17的結點是否存在,過程如下:

資料結構--2-3樹

插入

向2-結點中插入新鍵

  要在2-3樹中插入一個新的結點,類似於二分搜尋樹的插入,先進行一次未命中的查詢,找到要插入的結點所在的位置,將其掛在樹的底部。 但這樣一來樹就無法保證完美平衡性。使用2-3的主要原因:在插入新的結點之後能夠繼續保持平衡。

  如果未命中的查詢結束於一個2-結點,就將這個2-結點替換為3-結點,將要插入的鍵儲存在其中即可。

  如果未命中的查詢結束於一個3-結點,分析過程如下。

資料結構--2-3樹

向一棵只含有一個3-結點的樹中插入新鍵

  在考慮一般情況之前,先假設我們需要向一棵只含有一個3-結點的樹中插入一個新鍵。這棵樹中有兩個鍵,所以在它唯一的結點中 已經沒有可插入新鍵的空間了。為了將新鍵插入,先臨時將新鍵存入該結點中,形成一個4-結點(含有3個鍵和4條連線)。建立一個4-結點很方便, 因為很容易將其轉化成為一棵由3個2-結點組成的2-3樹,其中一個結點(根)含有中鍵,一個結點含有3個鍵中的最小者(和根結點的左連結相連), 一個結點含有3個鍵中的最大者(和根結點的右連結相連)。這棵樹即是一棵含有3個結點的二叉查詢樹,同時也是一棵完美平衡的2-3樹,因為其中所有的 空連結到跟結點的距離都相等。插入前樹的高度是0,插入後樹的高度是1。

資料結構--2-3樹

向一個父結點為2-結點的3-結點中插入新鍵

  假設未命中的查詢結束於一個3-結點,而它的父結點是一個2-結點。在這種情況下需要:在維持樹的完美平衡的前提下為新鍵 騰出空間。 需要像剛才一樣構造一個臨時的4-結點並將其分解,但此時不會為中鍵建立一個新結點,而是將其移動到原來的父結點中。

  將這次轉換看成將指向原3-結點的一條連結替換為新父結點中的原中鍵左右兩邊的兩條連結,並分別指向兩個新的2-結點。 根據假設,父結點中石油空間的:父結點是一個2-結點,插入之後變成了一個3-結點。另外,這次轉換也不影響(完美平衡的)2-3樹的 主要性質。樹仍然是有序的,因為中鍵被移到父節點中去了;樹仍然是完美平衡的,插入後所有的葉子結點到根結點的距離仍然相同。

上述過程是2-3樹動態變化的核心,圖示展示如下:

資料結構--2-3樹

向一個父結點為3-結點的3-結點中插入新鍵

  假設未命中查詢結束於一個父結點為3-結點的3-結點。依舊需要構造一個臨時的4-結點並分解它,然後將它的中鍵插入它的父結點中。由於父結點也是一個3-結點,插入中間後又形成一個新的臨時4-結點,然後在這個節點上進行相同的變換,集分解這個父結點並將它的中鍵插入的它的父結點中去。推廣到一般的情況,就是這樣一直向上不斷分解臨時的4-結點並將中鍵插到更高層的父結點,直到遇到一個2-結點並將它替換為一個不需要繼續分解的3-結點,或者是到達3-結點的根。

圖示過程如下:

資料結構--2-3樹

分解根結點

  如果從插入節點到根結點的路徑上都是3-結點,根結點最終變成一個臨時的4-結點。此時可以按照向一棵只有一個*3-結點的樹中插入新鍵的方法處理這個問題。將臨時的4-結點分解為三個2-結點**,樹高加1。這次最後的變化仍然保持了樹的完美平衡性,因為它變換的是根結點。

圖示過程如下:

4-結點的分解

  在2-3樹4-結點出現的位置有如下的幾種情況。

  • 1.根結點

  • 2.父結點為2-結點的左子結點或右子節點

  • 3.父節點為3-節點的左子節點、中間的子結點或右子結點

下面我們來詳細看一下在2-3樹中出現上述的位置時如何分解。

情形:

當臨時的4-節點出現在根節點:

資料結構--2-3樹

當臨時的4-節點出現在2-結點的左側:

資料結構--2-3樹

當臨時的4-節點出現在2-結點的右側:

資料結構--2-3樹

當臨時的4-節點出現在3-結點的左側:

資料結構--2-3樹

當臨時的4-節點出現在3-結點的中間:

資料結構--2-3樹

當臨時的4-節點出現在3-結點的右側:

資料結構--2-3樹

上述的情況中,在變化的過程中,只有當根節點最後為臨時的4-節點,此時被分解成為3個2-結點時,整個樹的高度才會增加1。除此之外,插入一個結點2-3樹的高度還是原來的高度。上述的變化過程中:任何空連結到根節點的路徑長度都是相等的。

結論

  在一棵大小為N的2-3樹中,查詢和插入的操作訪問的結點必然不會超過lgN。

  • 證明:

一棵含有N個結點的2-3樹的高度在在log2 N和log3 N之間。


個人微信公眾號:

資料結構--2-3樹
個人github:

github.com/FunCheney

相關文章