zoukankan      html  css  js  c++  java
  • RBTree 红黑树

     红黑树

    一、红黑树概述

      红黑树不仅是一个二叉搜索树,并且满足以下规则:

        1>每个节点不是红的就是黑的,

        2>根结点为黑色,

        3>如果节点为红色,其子节点必须为黑色,

        4>任一节点至NULL(树尾端)的任何路径,所含的黑节点的树木必须相同

    二、红黑树上结点的插入

     

        下面分6种情况介绍红黑树的插入操作:
        1 插入点的父亲为红,父亲的兄弟节点为黑,插入点在外侧   ///把父亲染红 祖父染黑 后右旋
        2 插入点的父亲为红,父亲的兄弟节点为黑,插入点在内侧  ///先左旋后把父亲染红 祖父染黑 后右旋
        3 插入点的父亲为红,父亲的兄弟节点为红,插入点在外侧  ///把父亲及父亲的兄弟染成黑色
        4 插入点的父亲为红,父亲的兄弟节点为红,插入点在外侧  ///(父亲的祖父节点为红)
        5 插入点的父亲为红,父亲的兄弟节点为红,插入点在内侧  ///先右旋父亲改为黑祖父为红后左旋(两次旋转)
        6 插入点的父亲为黑,直接插入
        这里判断父节点是否为祖先节点的左节点和 取得伯父节点,判断伯父节点的颜色的目的是为了识别以上者6种情况


        针对双黑结点的兄弟做一次右旋转,结果使双黑结点的近侄子成为双黑结点新的兄弟;
        将新兄弟结点着为双黑结点的父结点的颜色,父结点着为黑色,再针对父做一次左旋转,

     

    三、红黑树删除操作

        

    一、普通二叉查找树删除一个结点:

    (1)待删除结点没有子结点,即它是一个叶子结点,此时直接删除

    (2)待删除结点只有一个子结点,则可以直接删除;如果待删除结点是根结点,则它的子结点变为根结点;如果待删除结点不是根结点,则用它的子结点替代它的位置。

    (3)待删除结点有两个子结点,首先找出该结点的后继结点(即右子树中数值最小的那个结点),然后将两个结点进行值交换(即:只交换两个结点的数值,不改变结点的颜色)并将待删除结点删除,由于后继结点不可能有左子结点,对调后的待删除结点也不会有左子结点,因此要把它删除的操作会落入情况(1)或情况(2)中。

    二、.红黑树的删除结点算法

      1.待删除结点有两个外部结点,操作如下:

        (1)直接把该结点调整为叶结点

        (2)若该结点是红色,则可直接删除,不影响红黑树的性质,算法结束

        (3)若该结点是黑色,则删除后红黑树不平衡。此时要进行“双黑”操作

                记该结点为V,则删除了V后,从根结点到V的所有子孙叶结点的路径将会比树中其他的从根结点到叶结点的路径拥有更少的黑色结点, 破坏了红黑树性质4。此时,用“双黑”结点来表示从根结点到这个“双黑”结点的所有子孙叶结点的路径上都缺少一个黑色结点。  
    双黑含义:该结点需要代表两个黑色结点,才能维持树的平衡

    红黑树删除操作 - 枫叶 - 枫叶

    图1

       如图1,要删除结点90,则删除后从根结点到结点90的所有子树结点的路径上的黑色结点比从根点到叶结点的路径上的黑结点少。因而,删除结点90后,用子结点NULL代替90结点,并置为“双黑”结点。

    2.  待删除结点有一个外部结点,操作为: 
        该节点是黑色,其非空子节点为红色 ;则将其子节点提升到该结点位置,颜色变黑

    3.“双黑”结点的处理

    分三种情况:(1)双黑色结点的兄弟结点是黑色,且子结点有红色结点

                          (2)双黑结点的兄弟结点是黑色,且有两个黑色结点

                           (3)双黑结点的兄弟结点是红色结点
     
    (1)双黑结点的兄弟结点是黑色,且子结点有红色结点
    A种情况:双黑结点远侄子结点(双黑结点若为左孩子,则双黑结点的兄弟结点的右孩子为远侄子结点;同理,处理双黑结点为右孩子)为红色,如图2
    处理方法:把兄弟结点染为双黑结点的父亲结点的颜色,把兄弟结点的右孩子染为黑色,再把父结点染为黑色;然后针对父结点进行一次左旋转,如科3
    红黑树删除操作 - 枫叶 - 枫叶                    红黑树删除操作 - 枫叶 - 枫叶
                            图2                                                                              图3
    B种情况:双黑结点近侄子结点(双黑结点若为左孩子,则双黑结点的兄弟结点的左孩子为近侄子结点;同理,处理双黑结点为右孩子)为红,如图4
     处理方法:针对双黑结点的兄弟做一次右旋转,结果使双黑结点的近侄子成为双黑结点新的兄弟;将新兄弟结点着为双黑结点的父结点的颜色,父结点着为黑色,再针对父做一次左旋转,如图5
    红黑树删除操作 - 枫叶 - 枫叶红黑树删除操作 - 枫叶 - 枫叶 
                                    图4                                                               图5
     (2)双黑结点的兄弟结点是黑色,且有两个黑色结点,如图6
     处理方法:把双黑结点的兄弟结点着为红色,双黑结点的父结点着为黑色;若父结点原来为红色,则算法结束;若父结点原来黑色,则将父结点作为双黑结点,继续调整,如图7
    红黑树删除操作 - 枫叶 - 枫叶红黑树删除操作 - 枫叶 - 枫叶 
                            图6                                                                      图7
      (3)双黑结点的兄弟结点是红色结点,如图8
    处理方法:单旋转为情况1或情况2,并改变双黑结点的兄弟结点的颜色及父结点的颜色(?????可能不完善),如图9
    红黑树删除操作 - 枫叶 - 枫叶红黑树删除操作 - 枫叶 - 枫叶 
     
    代码实现如下:
    #include <iostream>
    #include <algorithm>
    #include <string.h>
    #include <stdio.h>
    #include <cmath>
    #include <queue>
    #include <vector>
    #include <map>
    #include <stack>
    #include <stdlib.h>
    #include <windows.h>
    
    
    using namespace std;
    
    typedef int Elemtype;
    #define RED 0
    #define BLACK 1
    
    typedef struct Node
    {
        Elemtype node;
        struct Node* left;
        struct Node* right;
        struct Node* prev;
        int color;
    } Node, * PNode;
    
    typedef struct RBTree
    {
        PNode root;
        PNode data;
    } RBTree, * PRBTree;
    
    int init(PRBTree tree)
    {   //红黑树的初始化
        if(tree == NULL) {
            return 0;
        }
        tree->data = (PNode)malloc(sizeof(Node));
        tree->data->color = BLACK;
        tree->root = tree->data;
        return 0;
    }
    void  rotate_left(PRBTree tree, PNode x)
    {
        PNode y = x->right;
        x->right = y->left;
        if(y->left != tree->data)
        {
            y->left->prev = x;
        }
        y->prev = x->prev;
        if(x == tree->root) {
            tree->root = y;
        }
        else if(x == x->prev->left) {
            x->prev->left = y;
        }
        else {
            x->prev->right = y;
        }
        y->left = x;
        x->prev = y;
    }
    
    ///右旋
    void rotate_right(PRBTree tree, PNode x)
    {
        PNode y = x->left;
        x ->left = y->right;
        if(y->right != tree->data)
        {
            y->right->prev = x;
        }
        y->prev = x->prev;
        if(x == tree->root) {
            tree->root = y;
        }
        else if(x == x->prev->left) {
            x->prev->left = y;
        }
        else {
            x->prev->right = y;
        }
        y->right = x;
        x->prev = y;
    }
    
    int insert_fixup(PRBTree tree, PNode e)
    {
        while(e->prev->color == RED)
        {
            if(e->prev->prev->left == e->prev) ///该节点的父亲节点是 左节点
            {
                if(e->prev->prev->right == RED)
                {
                    e = e->prev->prev;
                    e->left->color = e->right->color = BLACK;
                    e->color = RED;
                }
                else
                {
                    if(e->prev->right == e)
                    {
                        e = e->prev;
                        rotate_left(tree, e);
                    }
                    e->prev->color = BLACK;
                    e->prev->prev->color = RED;
                    rotate_right(tree, e->prev->prev);
                }
            }
            else    ///该节点的父亲节点是 右节点
            {
                if(e->prev->prev->left->color == RED)
                {
                    e = e->prev->prev;
                    e->left->color = e->right ->color = BLACK;
                    e->color = RED;
                }
                else
                {
                    if(e->prev->left == e)
                    {
                        e = e->prev;
                        rotate_right(tree, e);
                    }
                    e->prev->color = BLACK;
                    e->prev->prev->color = RED;
                    rotate_left(tree, e->prev->prev);
                }
            }
        }
        tree->root->color = BLACK;
        return 0;
    }
    
    PNode insertNode(PRBTree tree, Elemtype e)
    {
        PNode t = NULL;
        PNode p = NULL;
        t = tree->root;
        int flag = 0;
        if(tree->root == tree->data)
        {
            tree->root = (PNode)malloc(sizeof(Node));
            tree->root->node = e;
            tree->root->color = BLACK;
            tree->root->prev = tree->root->left = tree->root->right = tree->data;
            return tree->root;
        }
        while(t != tree->data)
        {
            p = t;
            if(e < t->node)
            {
                flag = 0;
                t = t->left;
            }
            else
            {
                if(e > t->node)
                {
                    flag = 1;
                    t = t ->right;
                }
                else
                {
                    if((flag = rand() % 2) == 0)
                    {
                        t = t->left;
                    }
                    else
                    {
                        t = t->right;
                    }
                }
            }
        }
        t = (PNode)malloc(sizeof(Node));
        t->node = e;
        t->color = RED;
        t->prev = p;
        t->left = t->right = tree->data;
        if(!flag)
        {
            p->left =  t;
        }
        else
        {
            p->right = t;
        }
        insert_fixup(tree, t);
        return t;
    }
    
    
    ///左旋
    
    
    
    ///找后继结点中-->右子树中数值最小的节点
    PNode next(PRBTree tree, PNode t)
    {
        if(t == tree->data)
        {
            return NULL;
        }
        while(t->right != tree->data);
        {
            t = t->right;
        }
        return t;
    }
    
    int delete_fixup(PRBTree tree, PNode c)
    {
        PNode b;
        while(c != tree->root && c->color == BLACK)
        {
            if(c == c -> prev->left)
            {
                b = c->prev->right;
                if(b->color == RED)
                {
                    b->color = BLACK;
                    c->prev->color = RED;
                    rotate_left(tree, c->prev);
                    b = c->prev->right;
                }
                if(b->right->color == BLACK && b->left->color == BLACK)
                {
                    b->color = RED;
                    c = c->prev;
                }
                else
                {
                    if(b->right->color == BLACK)
                    {
                        b->color = RED;
                        b->left->color = BLACK;
                        rotate_right(tree, b);
                        b = c->prev->right;
                    }
                    b->color = b->prev->color;
                    b->prev->color = BLACK;
                    b->right->color = BLACK;
                    rotate_left(tree, c->prev);
                    c = tree->root;
                }
            }
            else
            {
                b = c->prev->left;
                if(b->color == RED)
                {
                    b->color = BLACK;
                    c->prev->color = RED;
                    rotate_right(tree, c->prev);
                    b = c->prev->left;
                }
                if(b->right->color == BLACK && b->left->color == BLACK)
                {
                    b->color = RED;
                    c = c->prev;
                }
                else
                {
                    if(b->left->color == BLACK)
                    {
                        b->color = RED;
                        b->right->color = BLACK;
                        rotate_left(tree, b);
                        b = c->prev->left;
                    }
                    b->color = b->prev->color;
                    b->prev->color = BLACK;
                    b->left->color = BLACK;
                    rotate_right(tree, c->prev);
                    c = tree->root;
                }
            }
        }
        c->color = BLACK;
        return 0;
    }
    
    
    ///删除节点
    PNode destory_node(PRBTree tree, PNode t)
    {
        PNode c = NULL;
        PNode d = NULL;
        Elemtype tmp;
        if(t == tree->data)
        {
            return NULL;
        }
        if(t->left != tree->data && t->right != tree->data) ///该节点有两个子节点 则找到该节点右子树中最小的值
        {
            d = next(tree, t);
            tmp = d->node;
            d->node = t->node;
            t->node = tmp;
        }
        else
        {
            d = t;
        }
        if(d->left == tree->data)
        {
            c = d->right;
        }
        else
        {
            c = d->left;
        }
        c->prev = d->prev;
        if(d->prev != tree->data)
        {
            if(d->prev->left == d)
            {
                d->prev->left = c;
            }
            else
            {
                d -> prev->right = c;
            }
        }
        else
        {
            tree->root = c;
        }
        if(d->color == BLACK)
        {
            delete_fixup(tree, c);
        }
        return d;
    }
    
    ///最小值
    int minnum(PRBTree tree)
    {
        PNode x = tree->root;
        while(x->left != tree->data)
        {
            x = x->left;
        }
        return x->node;
    }
    int get_root(PRBTree tree)
    {
        PNode x = tree->root;
        return x->node;
    }
    ///最大值
    int maxnum(PRBTree tree)
    {
        PNode x = tree->root;
        while(x->right != tree->data)
        {
            x = x->right;
        }
        return x->node;
    }
    
    PNode mmap[110];
    void print(PRBTree tree)
    {
        PNode x = tree->root;
        int front = 0;
        int rear = 0;
        if(tree == NULL)
        {
            printf("NULL
    ");
            return;
        }
        PNode tmp;
        mmap[rear] = x;
        int count = 1;
        int temp = 0;
        while(front <= rear)
        {
            tmp = mmap[front++];
            count--;
            if(tmp->left != tree->data)
            {
                mmap[++rear] = tmp->left;
                temp++;
            }
            if(tmp->right != tree->data)
            {
                mmap[++rear] = tmp->right;
                temp++;
            }
            printf("%d  color = -->", tmp->node);
            if(tmp->color == BLACK)
            {
                printf("BLACK   |");
            }
            else
            {
                printf("RED     |");
            }
            if(count == 0)
            {
                count = temp;
                temp = 0;
                printf("
    ");
            }
        }
        return ;
    }
    PNode get_root1(PRBTree tree)
    {
        return tree->root;
    }
    int main()
    {
        PNode p ;
        RBTree tree ;
        init(&tree);
        int i;
        PNode tt , ttt;
        tt = insertNode(&tree, 1);
        insertNode(&tree, 2);
        insertNode(&tree, 3);
        insertNode(&tree, 4);
        insertNode(&tree, 5);
        insertNode(&tree, 6);
        insertNode(&tree, 7);
        insertNode(&tree, 8);
        insertNode(&tree, 9);
        insertNode(&tree, 10);
        insertNode(&tree, 11);
        insertNode(&tree, 12);
        p = get_root1(&tree);
        printf("根是------>%d
    ", get_root(&tree));
        printf("根是------>%d
    
    ", p->node);
        int mmin = minnum(&tree);
        int mmax = maxnum(&tree);
        printf("mmin  =  %d
    ", mmin);
        printf("mmax  =  %d
    
    ", mmax);
        print(&tree);
        printf("
    删除 %d 之后树的结构是:
    
    ", tt->node);
        ttt = destory_node(&tree, tt);
        print(&tree);
        return 0;
    }

    输出结果是:

    根是------>4
    根是------>4
    
    mmin  =  1
    mmax  =  12
    
    4  color = -->BLACK   |
    2  color = -->BLACK   |8  color = -->BLACK   |
    1  color = -->BLACK   |3  color = -->BLACK   |6  color = -->RED     |10  color = -->RED     |
    5  color = -->BLACK   |7  color = -->BLACK   |9  color = -->BLACK   |11  color = -->BLACK   |
    12  color = -->RED     |
    
    删除 1 之后树的结构是:
    
    8  color = -->BLACK   |
    4  color = -->BLACK   |10  color = -->BLACK   |
    2  color = -->BLACK   |6  color = -->RED     |9  color = -->BLACK   |11  color = -->BLACK   |
    3  color = -->RED     |5  color = -->BLACK   |7  color = -->BLACK   |12  color = -->RED     |
  • 相关阅读:
    腾讯安全上海游戏部门笔试题
    2017
    2016
    2015
    2014
    2013
    2012
    2011
    2010
    2009
  • 原文地址:https://www.cnblogs.com/chenyang920/p/5139021.html
Copyright © 2011-2022 走看看