当前位置:   article > 正文

《算法导论》第18章 B树_算法导论 b树

算法导论 b树

源码地址

1. B树的定义

B树示意图:

B树示意图

// 保存在B树中的关键字,同时也可以保存其他数据
type Key interface {
    CompareTo(other Key) int
    String() string
}

type BTree struct {
    root *BTreeNode
    t    int // 最小度数,除根节点外的内部节点至少有t个孩子,至多2t个孩子
}

type BTreeNode struct {
    keys     []Key        // 关键字
    children []*BTreeNode // 孩子节点
    isLeaf   bool         // 是否是叶子节点
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 关键字是以升序排列的(k[0] <= k[1] <= … <= k[n-1])
  • 关键字和子结点的关系

    NODE1的关键字都比k1小或等于,NODE2的关键字介于k1和k2之间,NODE3的关键字介于k2和k3之间,NODE4的关键字大于k3。

    关键字的个数用树的最小度数t来衡量,除根节点外的结点最少t-1个关键字,最多2t-1个,相对应的,除根节点外的结点最少t个孩子,最多2t个。

    关键字达到2t-1个时称该结点是满的。

  • 每个叶子结点都有相同的深度,即树高h。

    如果n(关键字个数)>=1,对任意一个包含n个关键字,高度为h,最小度数t>=2的B树:

    h从0开始计算

2. B树上的操作

2.1 插入关键字

如果一个节点是满的(关键字个数为2*t-1个),此时就不能再插入了,所以引入一个分裂节点的操作,将一个满节点从中间分裂为两个,将中间的关键字提升到父节点中,分裂后的两个节点各有t-1个关键字。

2.1.1 分裂满节点

假设t==3, x.child[i]指向的节点是一个满节点:

将y节点分裂成两个,y和z,各有t-1个关键字和t个子节点

将z节点当做x的第i+1个子节点,原来的child[i+1]及之后的子节点依次后移

将中间关键字k2当做x的keys[i],原来的keys[i]及之后的关键字依次后移

相关代码:

// splitChild分裂x的第i个子节点,x是非满的内部节点,x的children[i]已满,现在要分裂children[i]节点
func (t *BTree) splitChild(x *BTreeNode, i int) {
    z := t.allocateNode() // 分裂出来的节点
    y := x.children[i]    // z将是y的兄弟节点
    z.isLeaf = y.isLeaf
    d := t.t

    // y后半部分关键字分给z
    // y和z各有d-1个关键字,y为keys[0..d-1),z为keys[d,2d-1),keys[d-1]被提到父节点中
    for j := d; j < 2*d-1; j++ {
        z.keys = append(z.keys, y.keys[j])
    }
    upKey := y.keys[d-1] // 将要提升的关键字
    y.keys = y.keys[0 : d-1]

    // 如果y不是叶子,将y后半部分的孩子节点也分给z,分t个
    if !y.isLeaf {
        for j := d; j < 2*d; j++ {
            z.children = append(z.children, y.children[j])
        }
        y.children = y.children[0:d]
    }

    // 将z插入到x.children中
    // y是x.children[i],那么z现在是x.children[i+1]
    x.children = append(x.children, nil)
    for j := len(x.children) - 1; j > i+1; j-- {
        // x有n个关键字,必然有n+1个子结点
        x.children[j] = x.children[j-1]
    }
    x.children[i+1] = z

    // 将提升上来的关键字插入到x.keys中
    // 分裂前y中所有关键字都比x.keys[i]小,分裂后提升上来的关键字也比x.keys
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/375498
推荐阅读
相关标签
  

闽ICP备14008679号