資料結構與演算法之2 3 4樹

2021-10-25 19:11:08 字數 4131 閱讀 2215

[外鏈轉存失敗,源站可能有防盜煉機制,建議將儲存下來直接上傳(img-y3sprlm2-1615947159678)( 「不太平衡的二叉樹」)]

對於乙個普通的二叉查詢樹, 我們可以發現乙個問題, 存在一定的可能性, 一般的二叉查詢樹會退化成一般的鍊錶.

上圖還沒有完全退化, 但是如果查詢6這個結點, 會比其他的葉子結點走更多的路程.

為了解決一般二叉查詢樹可能帶來的退化問題, 引入了平衡樹的概念.

完全二叉樹和滿二叉樹是平衡樹.

平衡樹的定義就是:左右子樹的高度差不大於1的樹.

[外鏈轉存失敗,源站可能有防盜煉機制,建議將儲存下來直接上傳(img-nd3yzkzg-1615947159680)( 「2-3-4樹」)]

2-3-4樹的意思就是二叉/三叉/四叉樹.

簡單起見, 可以把2-3-4樹定義為四叉樹, 乙個結點可以儲存三個元素和四個孩子結點的指標.

如上圖, 先約定左中右三個元素代號是a,b,c; 從左到右的四個孩子結點的指標是a,b,c,d.

可以看到, 每個結點元素不一定要填滿, 每個子結點指標也不一定要填滿.

和二叉查詢樹類似, 每個結點的子樹也是根據元素與結點大小劃分的.

所以, 查詢乙個結點的時候, 根據被查詢元素pa/b/c的大小關係, 走不同的路徑來查詢元素.

以下, 是查詢元素4的搜尋路徑.

[外鏈轉存失敗,源站可能有防盜煉機制,建議將儲存下來直接上傳(img-qlpkpj6p-1615947159682)( 「2-3-4樹-查詢」)]

對2-3-4樹的插入操作需要分類討論, 根據不同的情況需要做對應對調整, 使插入後的樹依然保持平衡.

[外鏈轉存失敗,源站可能有防盜煉機制,建議將儲存下來直接上傳(img-yyp5z1tb-1615947159683)( 「2-3-4樹-直接插入」)]

對插入結點是不滿的葉子結點的情況, 和查詢元素類似, 根據大小關係找到被插入元素在樹中的位置, 因為結點沒有插入滿, 所以元素可以直接插入.

[外鏈轉存失敗,源站可能有防盜煉機制,建議將儲存下來直接上傳(img-x6g9wmvh-1615947159685)( 「2-3-4樹-插入滿葉子結點」)]

如果發現插入的結點是滿葉子結點, 則需要進行調整.

首先, a元素不動.

調整b元素

我們僅擷取需要調整對那顆子樹.

[外鏈轉存失敗,源站可能有防盜煉機制,建議將儲存下來直接上傳(img-n2ztzzxx-1615947159686)( 「2-3-4樹-調整b元素」)]

將b元素插入到父結點;

調整c元素

[外鏈轉存失敗,源站可能有防盜煉機制,建議將儲存下來直接上傳(img-vo9omake-1615947159686)( 「2-3-4樹-調整c元素」)]

新建乙個被調整結點對兄弟結點. 將c元素插入兄弟結點.

所以, 最終的插入結果是

[外鏈轉存失敗,源站可能有防盜煉機制,建議將儲存下來直接上傳(img-m4eyish0-1615947159687)( 「2-3-4樹-插入後」)]

[外鏈轉存失敗,源站可能有防盜煉機制,建議將儲存下來直接上傳(img-ipz8iwcj-1615947159688)( 「2-3-4樹-插入滿非葉子結點」)]

如果發現插入的結點是滿非葉子結點, 情況稍微複雜一點, 需要考慮被調整結點的子結點.

同樣, a元素不動.

調整b元素

[外鏈轉存失敗,源站可能有防盜煉機制,建議將儲存下來直接上傳(img-ggout6ok-1615947159688)( 「2-3-4樹-調整b元素」)]

如果被調整結點沒有父結點, 則新建乙個父結點, 將b元素插入父結點.(也就是說, 被調整結點是根結點.)

如果被調整結點有父結點, 則將b元素插入父結點.

調整c元素

[外鏈轉存失敗,源站可能有防盜煉機制,建議將儲存下來直接上傳(img-ghjvxd8f-1615947159689)( 「2-3-4樹-調整c元素」)]

新建乙個被調整結點對兄弟結點. 將c元素插入兄弟結點.

同時, 將c,d也插入到兄弟結點.(這個可以理解為c帶著他的左右孩子一起插入到兄弟結點, a帶著他的左右孩子一起留在原來的結點)

總結一下上面的操作, 其是就分為兩種: 直接插入和**後插入

直接插入

在元素插入的結點不滿的時候, 可以使用直接插入操作, 這裡就不再贅述.

[外鏈轉存失敗,源站可能有防盜煉機制,建議將儲存下來直接上傳(img-omv7t1i7-1615947159690)( 「2-3-4樹-直接插入」)]

元素5直接插入到4的右邊.

結點**

在元素插入的結點滿的時候, 需要進行結點**操作. 簡單來說, 就是將中間元素放到父結點, 如果沒有父結點則新建父結點, 然後將右元素及其孩子**出去, 作為當前結點的兄弟結點.

[外鏈轉存失敗,源站可能有防盜煉機制,建議將儲存下來直接上傳(img-ifo8hrph-1615947159690)( 「2-3-4樹-**」)]

元素6在結點**後插入到5的右邊.

可以認為,aba的孩子,cdc的孩子, 所以ac移動時, 需要帶上自己的孩子.

找到被刪除元素的位置, 標記為d中序遍歷dd的中序遍歷的後繼元素d'替換d, 將d'作為被刪除元素d如果d在葉子結點, 則退出, 否則回到2

[外鏈轉存失敗,源站可能有防盜煉機制,建議將儲存下來直接上傳(img-xdekfo8u-1615947159691)( 「2-3-4樹-刪除非葉子結點」)]

如上, 我們要刪除元素5, 則先找到元素5, 然後中序遍歷, 5的後繼元素是7, 則用7替換5;

再將7的位置標記為待刪除元素, 中序遍歷之, 其後繼元素是8, 所以用8替換, 且8在葉子結點, 則退出;

被刪除元素在葉子結點且不是2結點

因為沒有孩子了, 所以此時直接刪除即可.

被刪除元素在葉子結點且是2結點

如果直接刪除, 會讓整顆樹看起來缺了一塊, 按照以下操作:

刪除該元素

如果兄弟結點不是2結點, 則父結點中的乙個元素下移到該結點, 兄弟結點的乙個元素上移到父結點, 退出

如果兄弟結點是2結點且父結點是3或4結點, 則兄弟的元素與父結點合併(實際上是作為插入操作, 插入父結點), 退出

如果兄弟結點是2結點且父結點是2結點, 則兄弟結點的元素與父結點合併, 形成3結點, 並將該結點作為考察結點, 回到2

以下:刪除元素6, 則按照規則2

[外鏈轉存失敗,源站可能有防盜煉機制,建議將儲存下來直接上傳(img-t0fiytxk-1615947159691)( 「2-3-4樹-刪除-1」)]

刪除元素6, 則按照規則3, 按照插入操作, 父結點滿了, 再插入元素3, 此時需要**

[外鏈轉存失敗,源站可能有防盜煉機制,建議將儲存下來直接上傳(img-ykuysxri-1615947159692)( 「2-3-4樹-刪除-2」)]

刪除元素6, 則按照規則4, 如果還沒有結束, 則重複2-3-4

[外鏈轉存失敗,源站可能有防盜煉機制,建議將儲存下來直接上傳(img-3nra8fgd-1615947159693)( 「2-3-4樹-刪除-3」)]

根據2-3-4樹的插入操作不難看出, 2-3-4樹是按照向上(生成/插入父結點)和向左(生成兄弟結點)擴充套件的, 所以插入操作不會導致2-3-4樹出現某顆子樹特別高的情況.

從刪除操作看, 刪除某個元素之後會盡量不齊, 無法不齊的情況, 則考慮先父親迭代(減少層數), 總之其目的是盡量保證葉子層是平的, 沒有坑坑窪窪.

資料結構之2 3 4樹

2 3 4樹是一種階為4的b樹。它是一種自平衡的資料結構,可以在o lgn 的時間內查詢 插入和刪除,這裡的n是樹中元素的數目。2 3 4樹和紅黑樹是等價的,也就是每個紅黑樹都可以轉化為一顆2 3 4樹,每個選擇操作也和2 3 4樹中的 操作對應。2 3 4樹是這樣一種資料結構,滿足如下性質 1 每...

Java資料結構之234樹

n叉樹簡介 每個節點只有乙個資料項,並且每個節點最多只有兩個子節點的樹稱為二叉樹。如果每個節點可以存多個 大於等於3 資料項,並且每個節點可以擁有多個 大於等於3 子節點的樹稱為n 大於等於3 叉樹。n叉樹相對於二叉樹而言,儲存相等數量的資料,n叉樹因為同一層存放的資料變多,相應樹的高度就變小,查詢...

資料結構 2 3 4樹與紅黑樹

前面講到了2 3樹,2 3樹是允許節點最多有三個子節點的樹,2 3樹中有2節點和3節點,2節點跟普通的二叉樹節點一樣,3節點ab就是的左子樹上的所有節點的值小於a,中子樹上所有節點的值大於a而小於b,右子樹上節點的值大於b。2 3樹是一種平衡樹。2 3 4樹跟2 3樹差不多,只不過是把節點的最大子節...