红黑树

红黑树是一种数据结构,C++的set, map,和linux的内存管理都是用红黑树实现的。红黑树也是一棵二叉查找树,但是因为其自身结构的特点,其本身非常均衡。时间复杂度为O(logn)。因为在每次插入一个节点或者删除一个节点,红黑树都要对此进行调整。
下面先介绍红黑树的特点,红黑树具有以下几个特征:


1.每个节点不是红色就是黑色的;
2.根节点总是黑色的;
3.每个叶节点是黑色的(nil)
4.如果节点是红色的,则它的子节点必须是黑色的(反之不一定);
5.从根节点到叶节点或空子节点的每条路径,必须包含相同数目的黑色节点(即相同的黑色高度)。


红黑树主要通过三种方式修正树的平衡,变色,左旋和右旋。
左旋和右旋的代码如下:
左旋:

void leftRotate(RBNode *x) {
    RBNode *y = x->right;
    x->right = y->left;
    if (y->left) {
        y->left->parent = x;
    }
    y->parent = x->parent;
    if (x->parent == nullptr) {
        root = y;
    }
    else if (x == x->parent->left) {
        x->parent->left = y;
    }
    else {
        x->parent->right = y;
    }
    y->left = x;
    x->parent = y;
}

右旋:

void rightRoate(RBNode *y) {
    RBNode *x = y->left;
    y->left = x->right;
    if (x->right) {
        x->right->parent = y;
    }
    x->parent = y->parent;
    if (y->parent == nullptr) {
        root = x;
    }
    else if (y == y->parent->left) {
        y->parent->left = x;
    }
    else {
        y->parent->right = x;
    }
    x->right = y;
    y->parent = x;
}

变色主要体现在插入和删除节点部分。插入和删除部分比较复杂,我在看书的过程中做了一些笔记。大家可以参考一下:
插入节点平衡调整如下:
插入节点平衡调整
删除节点的调整如下:
这里写图片描述

这两部分的代码如下:

void insertFixUp(RBNode *z) {
    RBNode *par, *gParent;
    while(z->parent != NULL && z->parent->color == RED) {
        par = z->parent;
        gParent = par->parent;
        if (par == gParent->left) {
            RBNode *uncle = gParent->right;
            if (uncle->color == RED) {
                par->color = BLACK;
                uncle->color = BLACK;
                gParent->color = RED;
                z = gParent;
                continue;
            }
            else if (z == par->right){
                leftRotate(par);
                RBNode *tmp = par;
                par = z;
                z = tmp;
            }
            par->color = BLACK;
            gParent->color = RED;
            rightRoate(gParent);
        }
        else {
            RBNode *uncle = gParent->left;
            if (uncle->color == RED) {
                par->color = BLACK;
                uncle->color = BLACK;
                gParent->color = RED;
                z = gParent;
                continue;
            }
            else if (z == par->left) {
                rightRoate(par);
                RBNode* tmp = par;
                par = z;
                z = par;
            }
            par->color = BLACK;
            gParent->color = RED;
            leftRotate(gParent);
        }
        root->color = BLACK;
    }
}

//插入一个节点
void insertNode(RBNode *z) {
    RBNode *y = nullptr;
    RBNode *x = root;
    while(x) {
        if (z->val < x->val) {
            x = x->left;
        }
        else {
            x = x->right;
        }
    }
    z->parent = y;
    if (y == nullptr) {
        z = root;
    }
    else if (z->val < y->val) {
        y->left = z;
    }
    else {
        y->right = z;
    }
    z->setColor(RED);
    insertFixUp(z);
}

void deleteFixUp(RBNode *x) {
    RBNode *other, *par;
    while ((x == nullptr || x->color == BLACK) && x != root) {
        par = x->parent;
        if (x == par->left) {
            other = par->right;
            if (other->color == RED) {
                other->color = BLACK;
                par->color = RED;
                leftRotate(par);
                other = par->right;
            }
            if ((other->left == nullptr || other->left->color == BLACK) && (other->right == nullptr && other->right->color == BLACK)) {
                other->color = RED;
                x = par;
            }
            else if (other->right == nullptr || other->right->color == BLACK) {
                other->left->color = BLACK;
                other->color = RED;
                rightRoate(other);
                other = par->right;
            }
            other->color = par->color;
            par->color = BLACK;
            other->right->color = BLACK;
            leftRotate(par);
            x = root;
            break;
        }
        else {
            other = par->left;
            if (other->color = RED) {
                other->color = BLACK;
                par->color = RED;
                rightRoate(par);
                other = par->left;
            }
            if ((other->left == nullptr || other->left->color == BLACK) && (other->right == nullptr && other->right->color == BLACK)) {
                other->color = RED;
                x = par;
            }
            else if (other->left == nullptr || other->left->color == BLACK) {
                other->right->color = BLACK;
                other->color = RED;
                leftRotate(other);
                other = par->left;
            }
            other->color = par->color;
            par->color = BLACK;
            other->left->color = BLACK;
            rightRoate(par);
            x = root;
            break;
        }
    }
    if (x) {
        x->color = BLACK;
    }
}

//删除一个节点
void deleteNode(RBNode *z) {
    RBNode *successor;
    if (!z->left || !z->right) {
        successor = z;
    }
    else {
        successor = z->right;
        while (successor->left != nullptr) {
            successor = successor->left;
        }
    }
    RBNode *nexts;
    if (successor->left) {
        nexts = successor->left;
    }
    else {
        nexts = successor->right;
    }
    if (successor->parent == nullptr) {
        root = nexts;
    }
    else if (successor == successor->parent->left) {
        successor->parent->left = nexts;
    }
    else {
        successor->parent->right = nexts;
    }
    if (successor != z) {
        z->val = successor->val;
    }
    if (successor->color == BLACK) {
        deleteFixUp(successor);
    }
}

红黑树的结构如下:

const int RED = 1;
const int BLACK = 0;
class RBNode {
public:
    int val;
    int color;
    RBNode *left;
    RBNode *right;
    RBNode *parent;
    RBNode() {
        val = -1;
        color = -1;
        left = nullptr;
        right = nullptr;
        parent = nullptr;
    }

    void setVal(int val) {
        val = val;
    }

    void setColor(int color) {
        color = color;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值