美文网首页
整理笔记[红黑树]

整理笔记[红黑树]

作者: 六十年目裁判长亚玛萨那度 | 来源:发表于2019-02-24 15:16 被阅读0次

红黑树的其实就是加了操作的AVL树,这一类的树形结构,主要区别就是调整维护,删除维护的策略不同。

因为红黑树的情况是高度对称的,那么所有的情况都能压缩一半。

插入操作

插入简单,主要难点在于插入操作的维护,插入操作需要维护的是什么呢?
站在插入点的祖父点看,插入点和插入点的父亲都是红色,这个时候就需要盘它。

插入情况

你插入点在4,5,6,7。并且他爹是红色(8种情况)。那就盘(tiao)它(zheng)。
如果他爹是黑色,黑点下插红点,满足条件,不调。

插入与插入调整操作
RBTNode *insert_maintain(RBTNode *root) {//插入策略
    if (!has_red_child(root)) return root;
    if (root->lchild->color == 0 && root->rchild->color == 0) {
        if (has_red_child(root->lchild) || has_red_child(root->rchild)) {
            root->color = 0;
            root->lchild->color = root->rchild->color = 1;
        }
        return root;
    } else if (root->lchild->color == 0 && has_red_child(root->lchild)) {
        if (root->lchild->rchild->color == 0) {
            root->lchild = left_rotate(root->lchild);
        }
        root = right_rotate(root);
    } else if (root->rchild->color == 0 && has_red_child(root->rchild)) {
        if (root->rchild->lchild->color == 0) {
            root->rchild = right_rotate(root->rchild);
        }
        root = left_rotate(root);
    } else {
        return root;
    }
    root->color = 0;
    root->lchild->color = root->rchild->color = 1;
    return root;
}


RBTNode *__insert(RBTNode *root, int key) {// 插入
    if (root == NIL) return init(key);
    if (root->key == key) return root;
    else if (root->key < key) root->rchild = __insert(root->rchild, key);
    else root->lchild = __insert(root->lchild, key);
    return insert_maintain(root);
}

RBTNode *insert(RBTNode *root, int key) {
    root = __insert(root, key);
    root->color = 1;
    return root;
}


删除操作:

删除的策略:为了调整和少操作,在删除点以后,不管这给点是什么颜色,直接把删除点的颜色叠加到他爹的点上,这样他爹的颜色就是1,2,这两种,然后需要维护的是颜色出现有2的情况。

删除的时候分为三种大情况:
1.删除点的度为2
2.删除点的度为1
3.删除点的度为0

删除度2,1,0:找前驱或者后继,交换值,删掉前驱后继
因为是一层一层下去的,递归回去的时候一层一层的维护。

删除的维护:

删除的情况

这个时候的关键点是双重黑点的兄弟点,1和4点爱是什么颜色就是什么颜色,因为不影响所以不确定。

1.双重黑的2点的兄弟点是红色(如图此时是3点),那么来一个以双重黑2点的父亲为根节点(此时是1)开始的右旋,调整后让3为根节点,3点改成黑色,然后这个时候2点的父亲是1点,在1点看,看1点的左儿子(2点的兄弟)是不是黑色,不是就继续调整,直到进入第2步。

2.双重黑的2点的兄弟点是黑色(如图此时是3点):

  • 双重黑点(根节点左儿子)的兄弟节点右儿子(根节点右儿子的右儿子)的(3点的右儿子)是黑色,那么以3点右旋,4点成为3的父亲,3点变成红色,双重黑的父亲左旋,4变成根节点,4点颜色变成双重黑父亲颜色,双重黑父亲颜色变成黑色,双重黑颜色减去一层
  • 双重黑点(根节点左儿子)的兄弟节点右儿子(根节点右儿子的右儿子)的(3点的右儿子)是红色,那么以3点父亲为root,左旋3点成为根节点,3点颜色变成双重黑父亲颜色,双重黑父亲颜色变成黑色,双重黑颜色减去一层

删除与删除调整操作:

RBTNode *erase_maintain(RBTNode *root) { // 删除策略
    if (root->lchild->color != 2 && root->rchild->color != 2) return root;
    #define UNFINE(a, b) (root->a->color == 2 && root->b->color == 1 && !has_red_child(root->b)) 
    if (UNFINE(lchild, rchild) || UNFINE(rchild, lchild)) {
        root->color += 1;
        root->lchild->color -= 1;
        root->rchild->color -= 1;
        return root;
    }
    #undef  UNFINE
    if (root->lchild->color == 2) {
        if (root->rchild->color == 0) {
            root = left_rotate(root);
            root->color = 1;
            root->lchild->color = 0;
            root->lchild = erase_maintain(root->lchild);
            return root;
        }
        root->lchild->color = 1;
        if (root->rchild->rchild->color != 0) {
            root->rchild = right_rotate(root->rchild);
            root->rchild->color = 1;
            root->rchild->rchild->color = 0;
        }
        root = left_rotate(root);
        root->color = root->lchild->color;
    } else {
        if (root->lchild->color == 0) {
            root = right_rotate(root);
            root->color = 1;
            root->rchild->color = 0;
            root->rchild = erase_maintain(root->rchild);
            return root;
        }
        root->rchild->color = 1;
        if (root->lchild->lchild->color != 0) {
            root->lchild = left_rotate(root->lchild);
            root->lchild->color = 1;
            root->lchild->lchild->color = 0;
        }
        root = right_rotate(root);
        root->color = root->rchild->color;
    }
    root->lchild->color = root->rchild->color = 1;
    return root;
}

RBTNode *__erase(RBTNode *root, int key) { // 删除
    if (root == NIL) return NIL;
    if (root->key < key) root->rchild = __erase(root->rchild, key);
    else if (root->key > key) root->lchild = __erase(root->lchild, key);
    else {
        if (root->lchild != NIL && root->rchild != NIL) {
            RBTNode *temp = preacessor(root);
            root->key = temp->key;
            root->lchild = __erase(root->lchild, temp->key);
        } else {
            RBTNode *temp = (root->lchild == NIL ? root->rchild : root->lchild);
            temp->color += root->color;
            free(root);
            return temp;
        }
    }
    return erase_maintain(root);
}

RBTNode *erase(RBTNode *root, int key) {
    root = __erase(root, key);
    root->color = 1;
    return root;
} 

其他结构操作:

typedef struct RBTNode {
    int key;
    int color;
    struct RBTNode *lchild, *rchild;
} RBTNode;


RBTNode *NIL;
__attribute__((constructor))
void init_NIL() {
    NIL = (RBTNode *)malloc(sizeof(RBTNode));
    NIL->key = 0;
    NIL->color = 1;
    NIL->lchild = NIL->rchild = NIL;
}

RBTNode *init(int key) {
    RBTNode *q = (RBTNode *)malloc(sizeof(RBTNode));
    q->key = key;
    q->color = 0;
    q->lchild = q->rchild = NIL;
    return q;
}

RBTNode *left_rotate(RBTNode *root) {
    RBTNode *temp = root->rchild;
    root->rchild = temp->lchild;
    temp->lchild = root;
    return temp;
}

RBTNode *right_rotate(RBTNode *root) {
    RBTNode *temp = root->lchild;
    root->lchild = temp->rchild;
    temp->rchild = root;
    return temp;
}

int has_red_child(RBTNode *root) {
    return root->lchild->color == 0 || root->rchild->color == 0;
}

RBTNode *preacessor(RBTNode *root) {
    RBTNode *temp = root->lchild;
    while (temp->rchild != NIL) temp = temp->rchild;
    return temp;
}

void  clear(RBTNode *root) {
    if (root == NIL) return ;
    clear(root->lchild);
    clear(root->rchild);
    free(root);
    return ;
}

相关文章

  • 整理笔记[红黑树]

    红黑树的其实就是加了操作的AVL树,这一类的树形结构,主要区别就是调整维护,删除维护的策略不同。 因为红黑树的情况...

  • 红黑树笔记

    红黑树笔记 红黑树是平衡二叉查找树的一种。为了深入理解红黑树,我们需要从二叉查找树开始讲起。 BST 二叉查找树(...

  • 红黑树笔记

    红黑树:R-B Tree [toc]参考:红黑树(一)之 原理和算法详细介绍红黑树(五)之 Java的实现 1 简...

  • 数据结构—树—红黑树

    红黑树概述 红黑树的插入 红黑树的删除

  • C++boolan part3_week3

    由于对红黑树理解不深,课后对红黑树进行了较深入的探索。 此笔记主要对红黑树进行归纳理解,其中不免参照网上资料 红黑...

  • TreeMap

    需要先了解红黑树,这是之前分析红黑树的文章。之前在分析红黑树时,我认为红黑树=二叉查找树+红黑平衡,关于二叉查找树...

  • 数据结构与算法-AVL 红黑树

    AVL树AVL树 算法红黑树红黑树 B站

  • [转载]红黑树

    https://zhuanlan.zhihu.com/p/24367771红黑树简介红黑树插入红黑树删除

  • 拿下红黑树

    红黑树 红黑树、2-3树的简单定义: 实现红黑树的基本结构以及添加操作(维护定义,左旋、右旋、颜色反转) 红黑树与...

  • 红黑树

    啥是红黑树,红黑树 = 二叉树

网友评论

      本文标题:整理笔记[红黑树]

      本文链接:https://www.haomeiwen.com/subject/ojyvyqtx.html