2-3樹與2-3-4樹
2-3樹
2-3樹是一棵自平衡的多路查詢樹,它並不是一棵二叉樹,具有如下性質:
(1)每個節點有1個或2個key,對應的子節點為2個子節點或3個子節點;
(2)所有葉子節點到根節點的長度一致;
(3)每個節點的key從左到右保持了從小到大的順序,兩個key之間的子樹中所有的key一定大於它的父節點的左key,小於父節點的右key。
如下圖所示,
為什麼會有2-3樹這種資料結構呢?是因為他的查詢複雜度比平衡二叉樹還高嗎?
其實不是的,實際上2-3樹的查詢時間複雜度也是為 O(logN) ,而出現這種多路查詢樹,主要是跟記憶體與磁碟互動有關。我們知道在記憶體IO的速度比磁碟IO要快的多的多,但是同樣空間大小的記憶體比硬碟要貴的多的多,像TB級別的資料庫不可能全部讀出來放到記憶體中去,太過昂貴,而且也沒必要,大部分資料是不經常用的,所以就需要記憶體與外存互相結合,而如果用平衡二叉樹這種資料結構,在大資料量的情況下,樹肯定會很高,此時查個數據對磁碟讀個幾千上萬次那肯定是不行的(有人可能說把資料的索引檔案全部放到記憶體中,然後把源資料放在硬碟中,這樣在記憶體中定位到源資料Id,然後去外存中取源資料,這樣肯定是不行的,不要以為索引檔案很小,像搜尋引擎的倒排索引檔案比原始檔還要大),所以用多路查詢樹這種資料結構,高階的情況下,樹不用很高就可以標識很大的資料量了,檢索次數就大大減少了,用這種資料結構去磁碟中存取資料,磁碟IO次數的次數也會很少。
因為2-3樹是一棵自平衡的多路查詢樹,所以構建跟維繫一棵2-3樹,就比二叉平衡樹要複雜的多了。
2-3樹的插入操作,首先一定是在葉子節點,另外如果2-3樹中已存在當前插入的key,則插入失敗, 下面就在這兩點的前提下,進行2-3樹插入流程的分析:
(1)如果待插入的節點只有1個key,則直接插入即可;
(2)如果待插入的節點有2個key,則對節點進行分裂,即2個key加上待插入的key,這3個key分裂成1個key跟兩個子節點,然後將分裂之後的3個key中的父節點看作向上層插入的key,然後重複(1)、(2)步驟,直到滿足2-3樹的定義性質。
如下圖所示,插入“7”,而此時節點“5”只有一個key,則直接插入即可,形成節點“5 7”。
此時如果再插入“6”,而節點“5 7”已經有2個key了,所以需要先進行分裂。
“5 7”節點與新插入的“6”分裂之後,如下圖所示,
此時需要將“6”向父節點插入,而父節點“13 30”又包含2個key,則需要再次分裂,即如下圖所示,“13 30”與“6”分裂成父節點為“13”,子節點為“6”跟“30”
再將節點“13”看作向父節點插入,而此時父節點“50”只有一個key,則將“13”與“50”直接合並即可,如下圖所示,完成節點的插入調整,如下圖所示
2-3樹節點的插入應該還算簡單,最好是自己再去找幾個2-3樹的圖自己手畫一下插入過程,加深下印象。下面再講2-3樹節點的刪除。
關於2-3樹節點的刪除,首先,如果刪除的key不存在,則刪除失敗,然後在此前提下來分析節點的刪除。跟講平衡二叉樹的節點刪除類似,總結也是兩個判斷:①刪除的是什麼節點?②刪除了節點之後是否符合滿足2-3樹的性質?
2-3樹有4種節點:1.僅1個key的葉子節點;2.有 2個key的葉子節點;3.僅1個key的非葉子節點;4.有2個key的非葉子節點。即 1個key與2個key的節點 和 是否為葉子節點 的組合。下面就從簡單到複雜的情況開始分析:
(1)當刪除的節點是2個key的葉子節點,則將要刪除的目標key刪除即可,此時原來待刪除的2個key的葉子節點,變成1個key的葉子節點,但是符合2-3樹;
(2)當刪除的節點是2個key的非葉子節點,則此時使用中序遍歷找到待刪除節點的後繼節點,然後將後繼節點與待刪除節點位置互換,此時就將問題轉化為刪除節點為葉子節點(平衡樹的非葉子節點中序遍歷後繼節點肯定葉子節點),如果該葉子是2個key,則跟情況(1)一樣,如果該節點是隻有1個key,則跟後面的情況(4)一樣;
(3)當刪除的節點是1個key的非葉子節點,實際上操作跟情況(2)是一樣的,即使用中序遍歷找到待刪除節點的後繼節點,然後將後繼節點與待刪除節點位置互換,此時問題轉化為刪除節點為葉子節點;
(4)當刪除的節點是1個key的葉子節點,則將節點刪除,此時樹肯定不滿足2-3樹的性質,也即肯定需要調整,但要分情況來進行調整,而總結起來就是當前待刪除的1個key的葉子節點,兄弟節點與父節點,分別是1個key還是2個key,即:
a.當父節點是1個key(即此時僅有一個兄弟節點),兄弟節點是2個key,則將兄弟節點的一個key上移成父節點,而父節點下移成子節點,也即跟2個key中插入新節點類似,拆成一父兩子,此時樹滿足2-3樹,完成調整。
b.當父節點是1個key,兄弟節點也是1個key,則此時將父節點與兄弟節點合併,將合併後的節點看成當前節點,然後重複(4)的判斷,即判斷合併後的當前節點的兄弟節點與父節點的情況,然後走對應的a.b.c處理,直到滿足2-3樹,完成調整。
c.當父節點是2個key,即此時有兩個兄弟節點,而兄弟節點又可能有多種情況,窮舉起來有:刪除節點的位置左中右3個,以及另外兩個兄弟節點是否為1個key或2個key的4種情況,總共3*4=12種。即,
i.若刪除的是左或右節點,且中間節點只有1個key,則此時父節點的一個key下移,與中間節點合併,此時父節點為1個key,兩個子節點,樹滿足2-3樹,完成調整;
ii.若刪除的是左或右節點,且中間節點有2個key,則此時父節點的一個key下移,中間節點的一個key上移與父節點合併,此時父節點為2個key,3個子節點,樹滿足2-3樹,完成調整;
iii.若刪除的是中間節點,且右節點只有1個key,則此時父節點的一個key下移,與右節點合併,此時父節點為1個key,兩個子節點,樹滿足2-3樹,完成調整;
iv.若刪除的是中間節點,且右節點有2個key,則此時父節點的一個key下移,右節點的一個key上移與父節點合併,此時父節點為2個key,3個子節點,樹滿足2-3樹,完成調整。
計:i與ii刪除左或右節點兩種情況,中間節點1個key或2個key兩種情況,兄弟節點1個key或2個key兩種情況,總共 2x2x2=8 種;刪除中間節點一種情況,iii與iv右節點1個key或2個key兩種情況,左節點1個或2個key兩種情況,總共 1x2x2=4 種; 4+8=12 種全齊,雖然場景有12種,但是處理的方式只有2種,一種是父節點下移與子節點合併,另一種是父節點下移成單獨一個子節點,然後2個key的子節點上移一個key與父節點合併。
還是畫幾個圖演示一下吧,如下圖所示,最簡單的刪除情況(1),待刪除的節點是2個key,直接對節點的key “5” 刪除即可,
若刪除節點是情況(2),如下圖所示,刪除“100”,而且此時“100”是非葉子節點且2個key,則找到後繼節點“120”與“100”互換位置,然後刪除“100”
結果如下圖所示,將問題轉化為刪除一個key的葉子節點,且父節點為2個key,即為情況(4),刪除的節點為右節點,且中間節點為一個key,也即為情況(4)中c的i,所以此時需要將父節點的一個key下移與中間節點合併
結果如下圖所示,將父節點的一個key “120”下移,與中間節點“80”合併,最後如下右圖所示,2-3樹調整完成。
再講另外一種,情況(4)中c的iv,如下圖所示,刪除節點“22”,而右兄弟節點是2個key,則需要將父節點的“30”下移成中間節點,然後右兄弟的一個key“40”上移與父節點合併,
此時情況(4)中c的iv調整結果如下右圖所示,
最後再講一種節點刪除的情況,就是滿二叉樹的情況,根據定義的性質,滿二叉樹也符合2-3樹,如果當滿二叉樹要刪除葉子節點時,是符合情況(4)中的b的,即將父節點與兄弟節點合併,此時樹的層數顯然不平衡,即,將合併後的節點看作被刪除的當前節點,而當前節點的兄弟節點與父節點依然是都是一個key,符合情況(4)的b,將父節點與兄弟節點合併,直至樹平衡。
另外,實際上節點刪除的情況中(2)(3)是可以整合到一起去處理的,即,刪除節點是非葉子節點,無論待刪除節點的key數是多少,都用中序排序找到後繼節點,然後把問題轉化為刪除一個key的葉子節點去處理。
備註:對於節點刪除中的(4)的 b 可能沒講明白,再補充說明一下,如下圖刪除節點“10”,符合(4)的 b 情況,則父節點“13”與兄弟節點“18”合併,
合併之後如下圖所示,此時符合(4)中 c 的 ii 情況,則父節點的key“22”下移,中間節點的key“30”上移,
變換結果如下圖所示,此時2-3樹已經調整完成。這裡需要注意的點是,由於之前說父子節點key的上下移對於葉子節點來說並沒有子節點,但對於非葉子節點的變換是對應左旋與右旋的,所以上一步的變換,是以節點“22”做左旋操作,由父節點“降級”為子節點,而原本子節點“30”晉升為父節點,並將“30”的左子節點出讓給“22”作為右子節點。
2-3-4樹
2-3-4樹只是在2-3樹的基礎上進行了擴充套件。2-3-4樹也是一棵自平衡的多路查詢樹,具有如下性質:
(1)任一節點只能是1個或2個或3個key,對應的子節點為2個子節點或3個子節點或4個子節點;
(2)所有葉子節點到根節點的長度一致;
(3)每個節點的key從左到右保持了從小到大的順序,兩個key之間的子樹中所有的key一定大於它的父節點的左key,小於父節點的右key,對於3個key的節點,兩兩key之間也是如此。
如下圖所示,
2-3-4樹插入節點跟刪除節點的處理,實際上跟2-3樹很像,特別是插入節點,基本上跟2-3樹是一模一樣,只是分裂的條件由2個key變成了3個key而已,即,
(1)如果待插入的節點不是3個key,則直接插入即可;
(2)如果待插入的節點有3個key,則對節點進行分裂,即3個key加上待插入的key,這4個key分裂成1個key跟2個子節點,然後將分裂之後的4個key中的父節點看作向上層插入的key,然後重複(1)、(2)步驟,直到滿足2-3-4樹的定義性質。
如下圖所示,插入“125”,而此時待插入節點有3個key,需要對節點進行分裂,
“100 125 130”節點分裂之後,如下圖所示,分裂成父節點“120”與兩個子節點“100”與“125 130”,此時將父節點“120”看作向上層插入的key,
而又由於“120”的上層節點是“60 70 80”是3個key的節點,則需要對3個key節點進行分裂,如下圖所示,分裂成父節點”70”與子節點“60”與“80 120”,
將父節點“70”看作向上層插入的key,此時上層節點“22 50”是2個key,則直接插入即可,結果如下圖所示,此時滿足2-3-4樹,完成調整。
2-3-4樹節點的插入就差不多這樣了,也比較簡單的,其實從前面到這裡可以看出一些規律,就是不管是二叉查詢樹也好,平衡二叉樹,以及2-3樹的節點插入,相對來說都算簡單,但是對於一棵樹節點的刪除卻比較複雜,有的甚至需要不斷的回溯到根節點才能把樹調整平衡。
所以,關於2-3-4樹節點的刪除也不簡單,至少比節點的插入要複雜麻煩的多,但這裡就講個大概,類比2-3樹節點刪除去推就可以推出來,思路是一致的。
2-3-4樹節點的刪除,首先,如果刪除的key不存在,則刪除失敗。類比2-3樹總結也是兩個判斷:①刪除的是什麼節點?②刪除了節點之後是否符合滿足2-3-4樹的性質?
2-3-4樹有4種節點,1個key與非1個key的節點 和 是否為葉子節點 的組合,即:1.非1個key的葉子節點;2.僅1個key的葉子節點;3.非1個key的非葉子節點;4.僅1個key的非葉子節點。
2-3-4節點刪除操作:
(1)當刪除的節點是非1個key的葉子節點,則將要刪除的目標key刪除即可;
(2)當刪除的節點是非葉子節點,無論待刪除節點的key是多少個,先使用中序遍歷找到待刪除節點的後繼節點,然後將後繼節點與待刪除節點位置互換,此時就將問題轉化為刪除節點為葉子節點(平衡樹的非葉子節點中序遍歷後繼節點肯定葉子節點),如果該葉子是非1個key,則跟情況(1)一樣,如果該節點是隻有1個key,則跟後面的情況(3)一樣;
(3)當刪除的節點是1個key的葉子節點,則將節點刪除,此時樹肯定需要調整,即:
a.當父節點是1個key(即此時僅有一個兄弟節點),兄弟節點是非1個key,則將兄弟節點的一個key上移成父節點,而父節點下移成子節點,此時樹滿足2-3-4樹,完成調整。
b.當父節點是1個key,兄弟節點也是1個key,則此時將父節點與兄弟節點合併,將合併後的節點看成當前節點,然後重複(3)的判斷,即判斷合併後的當前節點的兄弟節點與父節點的情況,然後走對應的a.b.c處理,直到滿足2-3-4樹,完成調整。
c.當父節點是非1個key,即此時有兩個或三個兄弟節點,此時看相鄰兄弟節點是否“豐滿”,也即是否為3個key,如下,
i.若刪除節點的相鄰兄弟節點為非3個key,則父節點的一個key下移,與相鄰兄弟節點合併,此時樹滿足2-3樹,完成調整;
ii.若刪除節點的相鄰兄弟節點為3個key,則父節點的一個key下移成1個key的節點,相鄰兄弟節點的一個key上移與父節點合併,此時樹滿足2-3樹,完成調整;
下面畫幾個圖演示一下吧,如下圖所示,符合(3)中的 b 情況,即對兄弟節點“18”與父節點“13”合併,
合併之後,如下圖所示,此時符合(3)中 c 的 ii 情況,即對節點“22”做左旋操作(參考2-3樹文章最後的備註部分),
左旋結果如下圖所示,此時2-3-4樹調整完成。
最後再重複一點,關於2-3-4樹節點刪除情況(3)中的 b :“將合併後的節點看成當前節點,然後重複(3)的判斷,即判斷合併後的當前節點的兄弟節點與父節點的情況” 這句話,由於此時合併後的當前節點,其兄弟節點,是帶有子節點的,所以此時重複(3)的判斷之後,如果是 c 中的 i 或 ii 情況,對於(兄弟)key的上移與(父)key的下移,對應的子節點是需要出讓的,即此時的變換,實際上為左旋或右旋,具體是左旋還是右旋,看對應的場景。
相關推薦
2-3樹與2-3-4樹
2-3樹 2-3樹是一棵自平衡的多路查詢樹,它並不是一棵二叉樹,具有如下性質: (1)每個節點有1個或2個key,對應的子節點為2個子節點或3個子節點; (2)所有葉子節點到根節點的長度一致; (3)每個節點的key從左到右保持了從小到大的順序,兩個
第五章---面向對象---1.封裝之如何實現屬性的隱藏/2.封裝的意義/3.封裝與擴展性/4.property的使用
bar print 意義 一個 為什麽 驗證 產生 get mod 1.封裝之如何實現屬性的隱藏 封裝: __x=1 # 把數據屬性隱藏 (如何實現隱藏) 類定義階段 __開頭發生了變形 __x --> _A__x特點: 1.在類外部無法直接:obj.__
Spring REST Docs 1.2.6.RELEASE 與 2.0.3.RELEASE 釋出
Spring REST Docs 1.2.6.RELEASE 與 2.0.3.RELEASE 釋出了,Spring REST Docs 是 RESTful 服務的測試驅動文件,使用 Asciidoctor 手工編寫內容結合使用 Spring MVC Test 框架自動生成
CentOS 7中實現Python 3.6與2.7共存及版本切換
貌似目前大多數Linux發行版本中自帶的Python還都是2.7.x系列,但是越來越多的包包都開始拋棄2.7.x版本了,記錄一下在CentOS 7中安裝Python 3.6實現與自帶2.7兩個版本共存並可以自由切換 1.安裝Python 3.6和pip 先新增阿里雲映象站
php 二叉樹 與赫夫曼樹
二叉樹 赫夫曼樹 在學習圖之前,中間休息了兩天,感覺二叉樹需要消化一下。所以中間去溫習了下sql,推薦一本工具書《程序員的SQL金典》看名字不像一本好書,但是作為一個不錯的SQL工具書還是可以小小備忘一下。涵蓋內容不詳細但是挺廣,覆蓋多種主流數據庫言歸正傳,以前知道折半查找,二叉樹的概念也是感覺挺有意
大話資料結構讀書筆記艾提拉總結 查詢演算法 和排序演算法比較好 第1章資料結構緒論 1 第2章演算法 17 第3章線性表 41 第4章棧與佇列 87 第5章串 123 第6章樹 149 第7章圖 21
大話資料結構讀書筆記艾提拉總結 查詢演算法 和排序演算法比較好 第1章資料結構緒論 1 第2章演算法 17 第3章線性表 41 第4章棧與佇列 87 第5章串 123 第6章樹 149 第7章圖 211
Tesra超算網路的2大優勢與2大創新
Tesra超算網路是由深算科技自主研發的專為AI(人工智慧)服務的超級計算網路。該專案致力於構建一個基於區塊鏈的分散式GPU計算網路,為高強度的人工智慧訓練提供算力租約服務。 技術優勢: 通過結合區/塊鏈激勵機制和GPU分散式運算架構,將閒置且分散於世界各地的G
從2-3-4樹到紅黑樹(下) Java與C的實現
歡迎探討,如有錯誤敬請指正 相關部落格: 1. 實現技巧 為了簡化程式碼和減少不必要的開銷,在具體的實現中我們定義一個偽根節點ROOT且只定義一個NIL節點。偽根節點的左子支永遠指向NIL節點,NIL節點的左右子支又指向它自身。偽根節點的右子支才表示真正的紅黑樹。 2. Java語言實現 packa
二叉搜尋樹與平衡二叉樹
二叉搜尋樹(BST)二叉搜尋樹也是一種樹,適用與一般二叉樹的全部操作,但二叉搜尋樹能夠實現資料的快速查詢性質:非空左子樹的所有鍵值小於其根節點的鍵值非空右子樹的所有鍵值大於其根節點的鍵值左右子樹都是二叉搜尋樹二叉搜尋樹的插入、查詢、刪除刪除主要分三種情況來討論:(1)要刪
紅黑樹與平衡二叉樹區別?
如果說平衡二叉樹是一個類的話,那麼紅黑樹就是該類的一個例項。演算法的書我丟久了,一下子也找不到,我是憑記憶說的。紅黑樹的演算法比較麻煩,但它的思想很好,如果理解了它的思想也就理解它的演算法,我也只記得思想,具體演算法記不得了。我就在這說說思想吧。紅黑樹有兩個重要性質:1、紅
完全二叉樹與滿二叉樹
去筆試了很多次,每次都有有關於二叉樹的題目,而且其中最多的是關於完全二叉樹,然而完全二叉樹在哥心中的形態一直很模糊,究其原因是我把完全二叉樹和滿二叉樹搞混了。其實滿二叉樹是完全二叉樹的特例,因為滿二叉樹已經滿了,而完全並不代表滿。所以形態你也應該想象出來了吧,滿指的是出了葉
【C++】滿二叉樹與完全二叉樹的區別及判斷
#include<iostream> #include<queue> using namespace std; struct BinaryTreeNode { char _data; BinaryTreeNode*_left; BinaryTreeNode*_right; Bi
經典搜尋演算法之2-3-4樹與紅黑樹
1.2-3-4樹 在筆者上篇文章中,介紹了B樹和B+樹,這裡我所說的2-3-4樹就是階為4的B樹。根據離散數學的圖論相關知識,可以證明2-3-4樹和紅黑樹是等價的。對於m階(m指的結點的最大分支數)B樹,其結點的值的個數n:1<=n<m。因此,對於2-3
完全二叉樹與滿二叉樹與霍夫曼樹
去筆試了很多次,每次都有有關於二叉樹的題目,而且其中最多的是關於完全二叉樹,然而完全二叉樹在哥心中的形態一直很模糊,究其原因是我把完全二叉樹和滿二叉樹搞混了。其實滿二叉樹是完全二叉樹的特例,因為滿二叉樹已經滿了,而完全並不代表滿。所以形態你也應該想象出來了吧,滿指的是出了
m階B+樹與m階B樹的主要差異在於:
在B+樹中,具有n個關鍵字的結點只含有n棵子樹,即每個關鍵字對應一棵子樹;而在B樹中,具有n個關鍵字的結點含有(n+1)棵子樹。 在B+樹中,每個結點(非根結點)關鍵字個數n的範圍是[m/2向上取整,
劍指offer 二叉樹與二叉搜尋樹最佳解彙總 Python
面試題6: 重建二叉樹 輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷
二叉樹與二叉查詢樹
一、樹的相關術語 樹是一種非線性的資料結構,以分層的形式儲存資料 樹由一組以邊連線的節點組成,如下: 樹的層數被定義為樹的深度 二、二叉樹 二叉樹是一種特殊的樹,規定每個節點的子節點不能超過兩個 通過將子節點的個數設定為2,可以高效地在樹
資料結構——2-3-4樹與紅黑樹
2-3-4樹與紅黑樹 2-3-4樹 前面講到了2-3樹,2-3樹是允許節點最多有三個子節點的樹,2-3樹中有2節點和3節點,2節點跟普通的二叉樹節點一樣,3節點AB就是的左子樹上的所有節點的值小於A,中子樹上
二叉排序樹與平衡二叉樹
二叉排序樹 : 特點: 1、如果它的左子樹不空,那麼左子樹上的所有結點值均小於它的根結點值; 2、如果它的右子樹不空,那麼右子樹上的所有結點值均大於它的根結點值; 3、它的左右子樹也分別為二叉查詢樹 如下如所示二叉查詢樹: 二叉查詢樹的插入和刪除都非常的方便,很好的解決了折半查詢新增刪除
m階B+樹與m階B樹的區別
在B+樹中,具有n個關鍵字的節點只含有n棵子樹,即每個關鍵字對應一個子樹;而在B