1. 约束
B+ 树的约束与 B 树类似,一棵
m
m
m 阶 B+ 树具有如下特点:
(1)根节点要么是一个叶节点,要么至少具有两个孩子节点;
(2)除根节点以外,每个内部节点都具有
[
⌈
m
/
2
⌉
,
m
]
[\lceil m/2\rceil, m]
[⌈m/2⌉,m] 个孩子节点,因此具有
[
⌈
m
/
2
⌉
−
1
,
m
−
1
]
[\lceil m/2\rceil -1, m-1]
[⌈m/2⌉−1,m−1] 个关键码;(有些定义中,要求关键码个数与指针个数相同)
(3)所有叶节点都处在树的同一层;
(4)每个节点都会按序存储关键码,介于关键码
k
e
y
1
key1
key1 和
k
e
y
2
key2
key2 之间的指针所指孩子节点所存储的关键码的范围为
[
k
e
y
1
,
k
e
y
2
)
[key1, key2)
[key1,key2)。
与 B 树不同的地方:
(1)B+ 树的内部节点只存储关键码,实际记录只存在于叶节点中;如果将 B+ 树作为纯粹的索引实现,叶节点存储关键码及指向相应记录的指针,而实际记录存储在单独的磁盘文件中。
(2)B+ 树的叶节点一般会链接起来,形成一个双链表,如此通过访问链表中的所有叶节点便可以遍历所有的记录,因此适合于范围查询。
(3)B+ 树叶节点存储的记录数可能多于或少于
m
m
m,只要叶节点至少达到半满即可。
(4)B+ 树的搜索过程必须一直往下直至达到相应的叶节点才可,因为只有叶节点才存储实际的记录。
(5)因为 B+ 树的内部节点只存储关键码而不存储记录,所以其内部节点可以存储更多的关键码,即拥有更多的分支(子树),所以,存储相同数量的关键码时,B+ 树会比 B 树更加“矮胖”。
通常情况下,要使 B+ 树一个节点的大小能填满一个磁盘块,节点中的“指针”实际上就是孩子节点所在的磁盘块号。
2. 搜索
(1)从根节点开始;
(2)在当前节点中对关键码进行二分搜索,然后沿着相应的分支继续往下,重复此步骤,直至到达叶节点;
(3)如果当前节点是叶节点且没有找到目标,则失败返回;否则,返回相应的记录。
3. 插入
设叶节点包含的记录数的范围为
[
⌈
L
/
2
⌉
,
L
]
[\lceil L/2 \rceil, L]
[⌈L/2⌉,L]。
(1)首先找到应当包含待插入关键码的叶节点
x
x
x;
(2)如果目标叶节点还有空闲的空间(记录数少于
L
L
L),则插入关键码,然后成功返回,否则继续往下执行;
(3)如果目标叶节点已经满了,则在插入关键码之后,将其等分为两个叶节点
x
1
,
x
2
x1, x2
x1,x2,然后将叶节点
x
2
x2
x2 中最小的那个关键码的一个副本提升到父节点
y
y
y 中,如果父节点仍有空闲的空间(关键码个数少于
m
−
1
m-1
m−1),则成功返回,否则继续往下执行;
(4)将父节点
y
y
y 分裂为两个节点
y
1
,
y
2
y1,y2
y1,y2,其中
y
1
y1
y1 包含前
⌊
m
/
2
⌋
\lfloor m/2\rfloor
⌊m/2⌋ 个关键码,
y
2
y2
y2 包含后
m
−
⌊
m
/
2
⌋
−
1
m-\lfloor m/2\rfloor-1
m−⌊m/2⌋−1 个关键码,然后将第
⌈
m
/
2
⌉
\lceil m/2\rceil
⌈m/2⌉ 个关键码提升至
y
y
y 的父节点
z
z
z,如果
z
z
z 仍有空闲的空间,则成功返回,否则继续执行此步骤。
4. 删除
(1)首先找到包含待删除关键码的叶节点
x
x
x,然后从中删除指定的关键码,如果删除后,
x
x
x 仍然达到半满,则成功返回,否则继续往下执行;
(2)若
x
x
x 的右(左)兄弟节点
y
y
y 包含的记录数大于
⌈
L
/
2
⌉
\lceil L/2 \rceil
⌈L/2⌉,则将
y
y
y 中最小(最大)的一个关键码及相应的记录移到
x
x
x 中,然后使用
y
y
y(
x
x
x)中最小的关键码替换父节点中处于
x
,
y
x,y
x,y 之间的那个关键码,最后成功返回;否则继续往下执行;
(3)如果
x
x
x 的左右兄弟节点都没有足够的关键码可借,则将
x
x
x 及其兄弟节点
y
y
y 合并为一个节点,并删除父节点
z
z
z 中处于
x
,
y
x,y
x,y 之间的那个关键码,若父节点
z
z
z 没有发生下溢,则操作成功返回,否则继续往下执行;
(4)若节点
z
z
z 的右(左)兄弟节点
w
w
w 包含有富余的关键码,则将节点
z
z
z 的父节点中处于
z
,
w
z,w
z,w 之间的那个关键码
A
A
A 下移到节点
z
z
z 中,然后将
w
w
w 中最小(最大)的那个关键码上移到父节点并替换
A
A
A,然后成功返回,否则继续往下执行;
(5)若节点
z
z
z 的左右兄弟
w
w
w 皆不富余,则将节点
z
,
w
z,w
z,w 合并为一个节点,然后将父节点中介于
z
,
w
z,w
z,w 之间的那个关键码
A
A
A 下移到合并后的节点中;如果此操作导致父节点也发生了下溢,则继续回到步骤(4),否则成功返回。
图示来自 http://www.cnblogs.com/nullzx/ 。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)