1. 程式人生 > >2-3樹刪除和插入操作的小結

2-3樹刪除和插入操作的小結

學習2-3的操作後,感覺插入和刪除的思想都不是特別複雜,但就是比較囉嗦。特別是刪除,要處理很多種情況,本質上刪除就是“合併”和“調整關鍵字的分佈”,但不同情況程式設計的細節上有點差別。用圖小結幾個典型的情況。

(一)2-3樹的插入

空樹的插入最簡單,建立一個節點即可。

對於非空樹,首先查詢到一個葉節點,沿著這個葉節點向上執行插入操作。

1.葉節點是2-node,直接把值插入到葉節點中。

2.葉節點是3-node,則需要分裂葉節點,並且在葉節點的父節點上執行插入操作。

  2.1如果父節點是2-node,直接把值插入到此父節點中;把上次分裂的兩個節點連結到父節點上。

  2.2如果父節點是3-node,則需要分裂父節點,並把上次分裂的兩個節點連結到父節點分裂後的兩個節點上。再在父節點的父節點上執行插入操作,如此迴圈,直到1)某個祖宗節點是2-node;2)分裂根節點,並生成一個新的根節點。

幾個插入的例子:

I. 將U插入到下面的樹中。


1.1 首先比較三個關鍵字值:N,R和U,找到中間的一個關鍵字:R,將R與U替換。得到


1.2 然後分裂根節點。得到兩個分裂的節點:


1.3跟節點被分裂,需要生成一個新的根節點,填入上次待插入的關鍵字:R,並把上次得到的兩個分裂後的節點連結到新的根節點。

 

II.將E插入到下面的樹中

2.1 需要插入的葉節點是3-node。我們首先找到三個關鍵字值:A,G,E中間的關鍵字,就是E。

不需要和葉節點中的關鍵字交換。然後分裂這個節點,得到:

 

2.2繼續對父節點(關鍵字是J的節點)進行插入操作。這個節點是2-node,將關鍵字E插入到這個節點中,同時把上次分裂得到的兩個節點也連結到這個節點上。

III 將K插入到下面的樹:

 

3.1 首先找到三個關鍵字值“G,I,K”中的中間一個,是”I”,用K替換I,得到


然後將節點分裂,得到:

3.2 繼續在父節點(包含關鍵字“D,L”的節點)中插入。找出三個關鍵字值“D,L,I“中間的一個值,它是“I”,不需要進行關鍵字的交換。然後分裂父節點,並且連結上次分裂的節點。得到:


3.3 在上一步關鍵字“I”還沒有被插入,繼續在包含關鍵字“N”的節點上進行插入。此節點是2-node,因此直接把I插入到這個節點中,同時連結上次分裂的兩個節點。得到:

(二)2-3樹的刪除

首先我們找到所在要刪除的關鍵字(假設是K)所在的節點。如果這個節點不是葉節點,就要找到中序排列時K後面的關鍵字所在的節點,這個節點一定是葉節點。然後交換這兩個關鍵字,那麼所刪除的關鍵字最終還是在一個葉節點中。

1. 葉節點是3-node,則非常簡單。

2. 葉節點是2-node,則需要討論很多種情況。羅列幾種典型的情況。

I 父節點是3-node

1.1刪除節點是左孩子,中間孩子是2-node


圓圈表示包含要刪除關鍵字的節點;三角形表示子樹,可能是空子樹。空子樹時,父節點就是葉節點。

刪除後得到新樹:

1.2刪除節點是左孩子,中間孩子是3-node


將關鍵字“a”移動空節點中,關鍵字“c”移到關鍵字“a”所在的節點內;調整中間的節點。得到新的樹:


對其它的情況:

i刪除節點是中間節點,右節點是2-node;

ii刪除節點是中間節點,右節點是3-node;

iii刪除節點是右節點,中間節點是2-node;

iv刪除節點是右節點,中間節點是3-node;

情況“i” and “iii”類似於“1.1”;情況“ii” and “iv”類似於“1.2”;

II父節點是2-node

2.1 刪除節點是左節點;右節點是2-node

刪除空節點;把關鍵字“a”移到其右孩子節點中(也就是包含“b”的節點中);為了維持樹的高度不變,把包含“a”的節點變為空節點。得到:

這時我們又得到包含空節點的樹,我們需要刪除新的空節點。根據新的空節點的父節點的情況再分類處理。直到沒有空節點了。

2.1 刪除節點是左節點;右節點是3-node


把關鍵字“a”移動到空節點中;關鍵字“b”移動中父節點中;調整右節點,我們得到:

對其它情況:

“刪除節點是右節點;左節點是2-node”類似於“2.1”;

“刪除節點是右節點;左節點是3-node”類似於“2.2”;

從上面例子可以看到,刪除一個關鍵字時,有時需要把空節點釋放;有時保留空節點,但調整關鍵字以及相應子樹。