学习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”;
从上面例子可以看到,删除一个关键字时,有时需要把空节点释放;有时保留空节点,但调整关键字以及相应子树。
本文总结了2-3树的插入和删除操作。插入操作包括空树插入、2-node和3-node的处理,删除操作涉及叶节点为2-node和3-node的不同情况。通过具体案例展示了如何在保持2-3树性质的同时进行节点分裂、合并和关键字调整。

6034

被折叠的 条评论
为什么被折叠?



