3.3.5 #
解答 #
注:英文版原文使用的是 “ignore the order of the subtrees”,也就是忽略子树的顺序。
我们将 N=6 时的树形简记为 [{3}, {2, 2, 3}]
,代表根结点是一个 3-结点,第二层有两个 2-结点和一个 3-结点。
一个 N=6 的示例:
// 'D', 'G', 'K', 'O', 'S', 'Y'
|--GO--|
D K SY
考虑插入元素的两种效用,一种是使 2-结点变成 3-结点(当前结点或者它的父结点);另一种是使树高增加,被插入元素的 3-结点(及其父 3-结点)变回 2-结点。这两种操作的顺序不影响最后的树形。
于是 N=7 时,我们有两种树形。
[{3}, {2, 3, 3}]
(插入到某个 2-结点)。
// 'D', 'G', 'K', 'O', 'S', 'Y', 'L'
// before
|--GO--|
D K SY
// after
|--GO--|
D KL SY
[{2}, {2, 2}, {2, 2, 2, 2}]
(插入到 3-结点,变成满二叉树)。
// 'D', 'G', 'K', 'O', 'S', 'Y', 'Q'
// before
|--GO--|
D K SY
// after
|--------O--------|
|--G--| |--S--|
D K Q Y
N=8,对于 N=7 时的第一种树形,如果向 3-结点插入,会触发树高增加,结果相当于向第二种满二叉树底层 2-结点中的某一个插入元素后的树形。向第一种树形的 2-结点插入则会变成一个全部由 3-结点构成的 2-3 树。
注:可以把这里插入到 2-结点的操作看作是插入到 3-结点的一种“拖延”,它只是延后了树高增加的变换,但对最后的树形没有影响。
[{3}, {3, 3, 3}]
(插入到唯一的 2-结点)
// 'D', 'G', 'K', 'O', 'S', 'Y', 'L', 'A'
// before
|--GO--|
D KL SY
// after
|--GO--|
AD KL SY
[{2}, {2, 2}, {2, 2, 2, 3}]
(插入到满二叉树底部任意一个 2-结点)
// 'D', 'G', 'K', 'O', 'S', 'Y', 'Q', 'Z'
// before
|--------O--------|
|--G--| |--S--|
D K Q Y
// after
|--------O--------|
|--G--| |--S--|
D K Q YZ
N=9,和 N=8 时类似,对于 N=8 时的第一种树形,插入底层任意一个 3-结点都会触发平衡,等同于满二叉树底部两个 2-结点各插入一个元素的树形。考虑第二种树形最底层各结点插入元素后的树形即可。
[{2}, {2, 2}, {2, 2, 3, 3}]
(插入到 3-结点同侧 2-结点)
// 'D', 'G', 'K', 'O', 'S', 'Y', 'L', 'A', 'C'
// before
|--GO--|
AD KL SY
// after
|--------G--------|
|--C--| |--O--|
A D KL SY
[{2}, {2, 2}, {2, 3, 2, 3}]
(插入到 3-结点对侧 2-结点)
// 'D', 'G', 'K', 'O', 'S', 'Y', 'L', 'A', 'J'
// before
|--GO--|
AD KL SY
// after
|--------K--------|
|--G--| |--O--|
AD J L SY
[{2}, {2, 3}, {2, 2, 2, 2, 2}]
(插入到 3-结点)
// 'D', 'G', 'K', 'O', 'S', 'Y', 'Q', 'Z', 'X'
// before
|--------O--------|
|--G--| |--S--|
D K Q YZ
// after
|--------O--------|
|--G--| |--SY--|
D K Q X Z
N=10
[{2}, {2, 2}, {2, 3, 3, 3}]
(插入到 2-结点)
// 'D', 'G', 'K', 'O', 'S', 'Y', 'L', 'A', 'C', 'B'
// before
|--------G--------|
|--C--| |--O--|
A D KL SY
// after
|--------G--------|
|--C--| |--O--|
AB D KL SY
[{2}, {2, 3}, {2, 2, 2, 2, 3}]
(插入到 3-结点下的 2-结点)
// 'D', 'G', 'K', 'O', 'S', 'Y', 'Q', 'Z', 'X', 'P'
// before
|--------O--------|
|--G--| |--SY--|
D K Q X Z
// after
|--------O--------|
|--G--| |--SY--|
D K PQ X Z
[{2}, {2, 3}, {2, 3, 2, 2, 2}]
(插入到 2-结点下的 2-结点)
// 'D', 'G', 'K', 'O', 'S', 'Y', 'Q', 'Z', 'X', 'J'
// before
|--------O--------|
|--G--| |--SY--|
D K Q X Z
// after
|--------O--------|
|--G--| |--SY--|
D JK Q X Z