红黑树

来源:互联网 发布:中国难民政策 知乎 编辑:程序博客网 时间:2024/06/07 23:29

红黑树是一种数据结构,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;    }};
原创粉丝点击