【Algorithms公开课学习笔记9】 符号表part2——平衡搜索树

Balanced Search Tree 平衡搜索树

0. 前言

上一篇文章,我们分析了二叉搜索树(BST传送门)。在二叉搜索树中,查找、插入、删除、ceiling和floor等操作的平均时间性能取决于树高。在极端情况下(如插入有序序列后),如果树高h过大,其时间性能将会变得很差。根据树的特点,通过平衡树操作可以有效地降低树的高度,从而达到理想的时间性能。这就是本篇文章的重点——平衡搜索树(BSTs)。

1. 2-3搜索树

基本概念

2-3树的是由若干个2-节点(2-node)和3-节点(3-node)构成的树。其基本特征是有序对称(symmetric order)和绝对平衡(perfect balance)。
2-节点:2-节点具有一个key和两个子链接
3-节点:3-节点具有两个key和三个子链接
有序对称:通过中序遍历将得到递增的序列(升序序列)
绝对平衡:从根节点到空链接的路径都是相同长度的

基本操作

查找操作:对比节点key值,如果大于key,查右子树;如果小于key,查左子树;直到等于key或查到空链接。特别地,对于3-节点,如果小于左key,查左子树;如果大于左key小于右key,查中子树;如果大于右key,查右子树;直到等于key或查到为空链接。
插入操作:查找到该节点key值的合适位置,插入节点。如果该节点变成3-节点,无需操作;如果该节点变成4-节点,则要将中间key值的节点上浮到父节点,以此类推。在上浮过程中,如果root节点成为4-节点,则中间key值节点成为新root节点,左右key值节点分离成为新root节点的子节点。

下图示意了三种上浮的情况:

性能分析

操作、插入、删除操作均~clgN,其中系数c取决于实现方法(0< c <1)
分析所得,最坏的情况下是lgN,做好的情况下是log3N(约为0.631 lgN)。

存在问题

现实中,直接实现2-3树是非常复杂的,主要有以下原因:

  • 维持多种类型的节点是冗余的(至少需要维持2-节点、3-节点和4-节点)
  • 需要多种比较才能降低树高
  • 需要增加树高以分离4-节点
  • 分离节点时的情况太多

2. (左倾)红黑树

基本概念

上一节分析了2-3树存在的问题就是实现起来非常复杂,因此引入了(左倾)红黑树来表示2-3树。(这样的话,实现红黑树就相当于实现了2-3树)

在红黑树中,存在以下特征:(结合下图)

  • 没有节点连接两条红链接
  • 每一条从根到空链接的路径中黑链接的数量的相等的
  • 红链接都是左倾的

当理解红黑树的特征之后,接着看看用红黑树来表示2-3树的方法:将红黑树中左倾的红链接水平放置,那么红链接所连接的两节点就构成了2-3树的3-节点,其他的构成2-节点。(结合下图)

基本操作

节点表示Node

由于每一个节点仅有一个链接指向父节点,因此对此链接标色,以区别红黑链接

private static final boolean RED = true;
private static final boolean BLACK = false;

private class Node{
    Key key;
    Value val;
    Node left, right;
    boolean color; // 父链接的标色
}

private boolean isRed(Node x){
    if (x == null) return false;
    return x.color == RED;
}

左旋left rotation

private Node rotateLeft(Node h){
    assert isRed(h.right);//判断右链接是否红,即是否右倾的情况
    Node x = h.right;
    h.right = x.left;
    x.left = h;
    x.color = h.color;
    h.color = RED;
    return x;
}

右旋right rotation

private Node rotateRight(Node h){
    assert isRed(h.left);//判断左链接是否红,即是否左倾的情况
    Node x = h.left;
    h.left = x.right;
    x.right = h;
    x.color = h.color;
    h.color = RED;
    return x;
}

跳色color flip

private void flipColors(Node h){
    assert !isRed(h);//判断
    assert isRed(h.left);
    assert isRed(h.right);
    h.color = RED;
    h.left.color = BLACK;
    h.right.color = BLACK;
}

通过左旋、右旋、跳色等操作,可以保持红黑树的对称有序绝对平衡的特点。

查找

基于红黑树实现的BSTs的查找操作与基本的BST的查找操作是一致的。


public Val get(Key key){
    Node x = root;
    while (x != null){
        int cmp = key.compareTo(x.key);
        if (cmp < 0) x = x.left;
        else if (cmp > 0) x = x.right;
        else return x.val;
    }
    return null;
}

插入

当插入一个节点(节点C)到一棵红黑树中,为了保持绝对平衡和对称有序的特点,存在以下情况:

插入的节本操作可以描述成:(结合下图)

  • 基本的BST插入操作,同时新插入的节点的附链接标成红色
  • 如果需要的话,左右旋转去平衡4-节点(一个节点同时连接两个红链接)
  • 通过跳色操作将红链接往上一层传递
  • 如果需要的话,旋转以保持所有的红链接左倾
  • 循环操作直到满足红黑树的所有特征

总结起来,在递归的场景下,就是以下三种情况:

  • 右链接红,左链接黑:左旋
  • 左链接红,左子节点的左链接红:右旋
  • 左右链接红:跳色
private Node put(Node h, Key key, Value val){

    if (h == null) return new Node(key, val, RED);//插入节点(递归出口)
    int cmp = key.compareTo(h.key);
    if (cmp < 0) h.left = put(h.left, key, val);
    else if (cmp > 0) h.right = put(h.right, key, val);
    else  h.val = val;

    if (isRed(h.right) && !isRed(h.left)) h = rotateLeft(h);
    if (isRed(h.left) && isRed(h.left.left)) h = rotateRight(h);
    if (isRed(h.left) && isRed(h.right)) flipColors(h);

    return h;
}

性能分析

通过红黑树实现的BST,其树高在通常情况下 ~lgN,在最坏的情况下不超过 ~2lgN

应用

JAVA:java.util.TreeMap ,java.util.TreeSet等数据结构
C++ STL:map, mutilmap, mutilset等数据结构
linux内核

3. B树

基本概念

B树是2-3树的泛化:在B树中,每个节点允许有M-1个子节点(子链接)。(M的取值视实际情况而定)
B树的特征如下:(结合下图)

  • 跟节点至少有两个子链接
  • 其他节点至少有M/2个子链接
  • 外部节点包含内部节点的key(叶节点就是外部节点)
  • 内部节点包含每个外部节点的首个key(用于索引)

基本操作

查找

  • 从根节点开始
  • 通过内部节点对比key,确定对应的链接
  • 通过链接确定存储key的外部节点

插入

  • 先查找新key的位置
  • 插入
  • 如果溢出,则要分离节点,并将首key存储在上一级的内部节点

应用

B树被广泛地应用在各操作系统的文件系统和数据库中。如windows的NTFS、Mac的HFS和SQL、ORACLE等各种主流数据库。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值