• 算法导论18.32 BTREEDELETE的伪代码


    【转】

    ——————————————————————————

    ——————————————————————————

    《算法导论》练习18.3-2 请写出B-TREE-DELETE的伪代码。

     

    与插入情况相对称,除了根结点外(根结点个数不能少于1),B树的关键字数不能少于t-1个。对于简单删除情况,如果我们定位到关键字处在某个结点中,如果这个结点中关键字个数恰好是t-1个,如果直接删除这个关键字,就会违反B树规则。


    此时,需要考虑两种处理方案:


    1)把这个结点与其相邻结点合并,合并时需要把父结点的一个关键字加进来,除非相邻的那个结点的关键字数也是t-1个,否则,合并后会超出2t-1的限制,同样违反B树规则。而且,因为从父结点拉下一个关键字,导致父结点的关键字数少1,如果原来父结点关键字数是t-1,那么父结点违反B树规则,这种情况下,必须进行回溯处理。(对于下图(a)初始树,删除结点Z就会出现这种情况)


    2)从相邻结点借一个关键字过来,这种情况要求,相邻结点必须有多于t-1个关键字,借的过程中,需要转经父结点,否则违反B树规则。

     

    为了避免回溯,要求我们在从树根向下搜索关键字的过程中,凡是遇到途经的结点,如果该结点的关键字数是t-1,则我们需要想办法从其他地方搞个关键字过来,使得该结点的关键字数至少为t

    搞,也是从相邻结点搞,如果相邻结点有的话,当然,也要经过父结点进行周转。如果没有,就说明相邻结点的关键字个数也是t-1,这种情况,直接对该结点与其相邻结点进行合并,以满足要求。

     

    B树的结点的合并基于如下情况调用:内结点x的第i个子结点y和第i+1个子结点z的关键字数都是t-1,此时需要把内结点x的第i个关键字下移与yz的合并,形成一个结点y

     

    B树中结点的合并:


    B-TREE-MERGE-CHILD(x, i, y,z)

    1 n[y] ← 2t -1

    2 for j ← t +1 to 2t -1

    3   do keyj[y] keyj-t[z]

    4 keyt[y] keyi[x]

    5 if not leaf[y]

    6  then for j ← t +1 to 2t -1

    7        do cj[y] cj-t[z]

    8 for j ← i +1 to n[x]

    9  do cj[x] cj+1[x]

    10 n[x] ← n[x] -1

    11 FREE-NODE(z)

    12 DISK-WRITE(y)

    13 DISK-WRITE(z)

    14 DISK-WRITE(x)

     


     

    B树的删除:


    B-TREE-DELETE(T,k)

    1  r  root[T]
     2  if n[r] = 1
     3    then DISK_READ(c1[r])
     4       DISK_READ(c2[r])
     5       y c1[r]
     6       z c2[r]
     7       if n[y] = n[z] = t-1                    Cases 2c or 3b
     8         then  B-TREE-MERGE-CHILD(r, 1, y, z) 
     9            root[T]  y
     10           FREE-NODE(r)
     11           B-TREE-DELETE-NONONE(y, k)
    12      else B-TREE-DELETE-NONONE (r, k)
    13 else B-TREE-DELETE-NONONE (r, k)
     

    考虑到根结点的特殊性,对根结点为1,并且两个子结点都是t-1的情况进行了特殊的处理:
    先对两个子结点进行合并,然后把原来的根删除,把树根指向合并后的子结点y
    这样B树的高度就减少了1。这也是B树高度唯一会减少的情况。 

    除了这种情况以外,就直接调用子过程B-TREE-DELETE-NONONE (x, k)

     

    B-TREE-DELETE-NONONE (x, k)

    1  i  1
     2  if leaf[x]                                        Cases 1
     3     then while i <= n[x] and k > keyi[x]
     4            do i  i + 1
     5               if k = keyi[x]
     6                 then for j ← i+1 to n[x]
     7                        do keyj-1[x] keyj[x]
     8                      n[x]  n[x] - 1
     9                      DISK-WRITE(x)
     10              else error:”the key does not exist”
     11    else while i <= n[x] and k > keyi[x]
    12           do i  i + 1
     13              DISK-READ(ci[x])
     14              y ci[x]
     15              if i <= n[x]
     16                then DISK-READ(ci+1[x])
     17                     z ci+1[x]
     18              if k = keyi[x]                           Cases 2
    19                then if n[y] > t-1                    Cases 2a
     20                       then k′←B-TREE-SEARCH-PREDECESSOR(y)
     21                            B-TREE-DELETE-NONONE (y, k)
     22                            keyi[x] k
     23                     else if n[z] > t-1                Cases 2b
     24                       then k′←B-TREE-SEARCH-SUCCESSOR (z)
     25                            B-TREE-DELETE-NONONE (z, k)
     26                            keyi[x] k
     27                     else B-TREE-MERGE-CHILD(x, i, y, z) Cases 2c
     28                          B-TREE-DELETE-NONONE (y, k)
     29              else                                    Cases 3
     30                if i >1
     31                  then DISK-READ(ci-1[x])
     32                       p ci-1[x]
     33                if n[y] = t-1 
     34                  then if i>1 and n[p] >t-1                Cases 3a
     35                         then B-TREE-SHIFT-TO-RIGHT-CHILD(x,i,p,y)
     36                       else if i <= n[x] and n[z] > t-1     Cases 3a
     37                         then B-TREE-SHIFT-TO-LEFT-CHILD(x,i,y,z)
     38                       else if i>1                        Cases 3b
     39                         then B-TREE-MERGE-CHILD(x, i, p, y)  
     40                              y ← p
     41                       else B-TREE-MERGE-CHILD(x, i, y, z) Cases 3b
     42                B-TREE-DELETE-NONONE (y, k)
     


    查找前驱

    B-TREE-SEARCH-PREDECESSOR(y)
    1  x ← y
    2  i  n[x]
    3  while not leaf[x]
    4    do DISK_READ(ci+1[x])
    5       x ci+1[x]
    6       i  n[x]
    7  return keyi[x]
     


    查找后继

    B-TREE-SEARCH-SUCCESSOR (z)
    1  x ← z
    2  while not leaf[x]
    3    do DISK_READ(c1[x])
    4       x c1[x]
    5  return key1[x]
     


    转移到右边的子结点

    B-TREE-SHIFT-TO-RIGHT-CHILD(x,i,y,z)
    1 n[z] ← n[z] +1
    2 j ← n[z]
    3 while j > 1
    4   do keyj[z] keyj-1[z]
    5      j ← j -1
    6 key1[z] keyi[x]
    7 keyi[x] keyn[y][y]
    8 if not leaf[z]
    9   then j ← n[z]
    10       while j > 0
    11         do cj+1[z] cj[z]
    12            j ← j -1
    13       c1[z] cn[y]+1[y]
    14 n[y] ← n[y] -1

    15 DISK-WRITE(y)

    16 DISK-WRITE(z)

    17 DISK-WRITE(x)




    转移到左边的子结点

    B-TREE-SHIFT-TO-LEFT-CHILD(x,i,y,z)
    1 n[y] ← n[y] +1
    2 keyn[y][y] keyi[x]
    3 keyi[x] key1[z]
    4 n[z] ← n[z] -1
    5 j ← 1
    6 while j <= n[z]
    7   do keyj[z] keyj+1[z]
    8      j ← j +1
    9 if not leaf[z]
    10  then cn[y]+1[y] c1[z]
    11       j ← 1
    12       while j <= n[z]+1
    13         do cj[z] cj+1[z]
    14            j ← j + 1

    15 DISK-WRITE(y)

    16 DISK-WRITE(z)

    17 DISK-WRITE(x)



    注意:每次递归调用前,程序都能保证包括关键字的子树根的关键字数至少为t(除了根结点外),

    这是B-TREE-DELETE-NONONE子过程能够正确运行的关键,类似的,

    可以用循环不变式证明B-TREE-DELETE-NONONE子过程的正确性。



    B树的删除

    B树删除续


     ————————————————————————————————————

    【转自】http://blog.csdn.net/swordmanwk/article/details/6549480

  • 相关阅读:
    Mysql主从复制,实现数据同步
    Redis加锁与解锁
    Git常用命令
    R语言实战(二)数据管理
    R语言实战(一)介绍、数据集与图形初阶
    [读书笔记]机器学习:实用案例解析(12)
    [读书笔记]机器学习:实用案例解析(11)
    [读书笔记]机器学习:实用案例解析(10)
    [读书笔记]机器学习:实用案例解析(9)
    [读书笔记]机器学习:实用案例解析(8)
  • 原文地址:https://www.cnblogs.com/longdouhzt/p/2131901.html
Copyright © 2020-2023  润新知