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