RBTree——红黑树

RBTree

RBTree:红黑树是一棵二叉搜索树,它在每个节点上增加了一个存储位来表示节点的颜色,可以是Red或Black。通过对任何一条从根到叶子简单路径上的颜色来约束,红黑树保证最长路径不超过最短路径的两倍,因而近似于平衡。


红黑树是平衡二叉搜索树的一种(平衡二叉搜索树中又有AVL Tree),满足二叉搜索树的条件外,还应买足下面的4个条件:
1. 每个节点不是红色就是黑色;
2.根节点是黑色;
3.如果节点是红,那么子节点为黑色;(所以新增节点的父节点为黑色)
4.任一节点到NULL(树尾端)的任何路径,所含的黑节点数必须相同;(所以新增节点为红色)


ps: cur为当前节点,p为父节点,g为祖父节点,u为叔叔节点


第一种:cur为红,p为红,g为黑,u存在且为红
则将p,u改为黑,g改为红,然后把g当成cur,继续向上调整。


这里写图片描述


第二种:cur为红,p为红,g为黑,u不存在/u为黑,p为g的左孩子,cur为p的左孩子,则进行右单旋转;相反,p为g的右孩子,cur为p的右孩子,则进行左单旋转p、g变色–p变黑,g变红


这里写图片描述


第三种:cur为红,p为红,g为黑,u不存在/u为黑,p为g的左孩子,cur为p的右孩子,则针对p做左单旋转;相反,p为g的右孩子,cur为p的左孩子,则针对p做右单旋转则转换成了情况2。


这里写图片描述


RBTree和AVLTree的对比:
红黑树和AVL树都是高效的平衡二叉树,增删查改的时间复杂度都是O(lg(N)),红黑树的不追求完全平衡,保证最长路径不超过最短路径的2倍,相对而言,降低了旋转的要求,所以性能会优于AVL树,所以实际运用中红黑树更多。


RBTree的应用:STL里边map和set,linux内核


#pragma once
#include <iostream>

using namespace std;
#include <stdio.h>

enum Colour
{
    RED,
    BLACK,
};

template<class K, class V>
struct RBTreeNode
{
    K _key;
    V _value;

    RBTreeNode<K, V>* _left;
    RBTreeNode<K, V>* _right;
    RBTreeNode<K, V>* _parent;

    Colour _colour; //类中枚举

    RBTreeNode(const K& key, const V& value) //拷贝构造
        :_key(key)
        , _value(value)
        , _left(NULL)
        , _right(NULL)
        , _parent(NULL)
        , _colour(RED)
    {}
};

template<class K, class V>
struct RBTree
{
    typedef RBTreeNode<K, V> Node;
public:
    RBTree()
        :_root(NULL)
    {}

    bool Insert(const K& key, const V& value) //插入
    {
        if (_root == NULL)
        {
            _root = new Node(key, value);
            _root->_colour = BLACK;

            return true;
        }

        Node* parent = NULL;
        Node* cur = _root;
        while (cur)//从根开始遍历
        {
            if (cur->_key < key)//插入值大于根 往右子树遍历
            {
                parent = cur;
                cur = cur->_right;
            }
            else if (cur->_key > key)//左
            {
                parent = cur;
                cur = cur->_left;
            }
            else
            {
                return false;
            }
        }
        // cur 即为要插入的位置
        // parent 即为原始叶子节点
        cur = new Node(key, value);
        cur->_colour = RED; // 插入的先预设为红 如果为黑 对整个树的影响过大

        //重建树的链式结构
        if (parent->_key < key)
        {
            parent->_right = cur;
            cur->_parent = parent;
        }
        else
        {
            parent->_left = cur;
            cur->_parent = parent;
        }

        // 旋转变化
        while (parent && parent->_colour == RED)
        {
            Node* grandfather = parent->_parent;
            if (parent == grandfather->_left) //左
            {
                Node* uncle = grandfather->_right; //由uncle决定怎么变化

                // 1.存在且为红
                // 2.不存在,存在且为黑
                if (uncle && uncle->_colour == RED)
                {
                    parent->_colour = uncle->_colour = BLACK;
                    grandfather->_colour = RED;

                    cur = grandfather;    // 往上推 看是否影响其他的节点
                    parent = cur->_parent;//
                }
                else 
                {
                    if (parent->_right == cur) //右边 左右双旋
                    {
                        RotateL(parent); //左旋

                        swap(cur, parent);
                    }

                    RotateR(grandfather); // 只右旋 一次
                    parent->_colour = BLACK;
                    grandfather->_colour = RED;
                }
            }
            else
            {
                Node* uncle = grandfather->_left;
                if (uncle && uncle->_colour == RED)
                {
                    parent->_colour = BLACK;
                    uncle->_colour = BLACK;
                    grandfather->_colour = RED;

                    // 继续往上更新
                    cur = grandfather;
                    parent = cur->_parent;
                }
                else // 不存在 / 存在且为黑
                {
                    if (cur == parent->_left) // 左边 右左双旋
                    {
                        RotateR(parent);
                        swap(cur, parent);
                    }

                    RotateL(grandfather);// 右边 只旋转一次 左旋
                    parent->_colour = BLACK;
                    grandfather->_colour = RED;
                }
            }
        }

        _root->_colour = BLACK; //暴力格式化根为黑

        return true;
    }

    void RotateR(Node* parent)
    {
        Node* subL = parent->_left;
        Node* subLR = subL->_right;
        Node* ppNode = parent->_parent;

        parent->_left = subLR;
        if (subLR)
            subLR->_parent = parent;

        subL->_right = parent;
        parent->_parent = subL;

        if (_root == parent)
        {
            _root = subL;
            subL->_parent = NULL;
        }
        else
        {
            if (ppNode->_right == parent)
            {
                ppNode->_right = subL;
            }
            else
            {
                ppNode->_left = subL;
            }

            subL->_parent = ppNode;
        }
    }


    void RotateL(Node* parent)
    {
        Node* subR = parent->_right;
        Node* subRL = subR->_left;
        Node* ppNode = parent->_parent;

        parent->_right = subRL;
        if (subRL)
            subRL->_parent = parent;

        subR->_left = parent;
        parent->_parent = subR;

        if (parent == _root)
        {
            _root = subR;
            _root->_parent = NULL;
        }
        else
        {
            if (ppNode->_left == parent)
            {
                ppNode->_left = subR;
            }
            else
            {
                ppNode->_right = subR;
            }

            subR->_parent = ppNode;
        }

    }

    void InOrder()  //析构函数
    {
        _InOrder(_root);

    }

    void _InOrder(Node* root)
    {
        if (root == NULL)
        {
            return;
        }

        _InOrder(root->_left);  
        cout << root->_key << " ";
        _InOrder(root->_right);
    }



    bool _IsBalance(Node* root, size_t blackNum, const size_t N)
    {
        if (root == NULL)
        {
            if (N != blackNum)
            {
                cout << "黑色节点的数量不相等" << endl;
                return false;
            }
            else
            {
                return true;
            }
        }

        if (root->_colour == BLACK)
        {
            ++blackNum;
        }

        if (root->_colour == RED
            && root->_parent->_colour == RED)
        {
            cout << "存在连续的红节点" << _root->_key << endl;

            return false;
        }

        return _IsBalance(root->_left, blackNum, N)
            && _IsBalance(root->_right, blackNum, N);
    }

    bool IsBalance()
    {
        if (_root && _root->_colour == RED)
        {
            return false;
        }

        size_t N = 0;
        Node* cur = _root;
        while (cur)
        {
            if (cur->_colour == BLACK)
            {
                ++N; //每条路径上的黑色节点数相同 故只用求一次单链的黑色节点数
            }

            cur = cur->_left;
        }

        size_t blackNum = 0;
        return _IsBalance(_root, blackNum, N);
    }




private:
    Node* _root;
};

void TestRBTree()
{
    //int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
    //int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
    //RBTree<int, int> t;
    //for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
    //{
    //  t.Insert(a[i], i);
    //}
    //t.InOrder();
    int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
    RBTree<int, int> t;
    for (size_t i = 0; i < sizeof(a)/sizeof(a[0]); ++i)
    {
        t.Insert(a[i], i);
        cout<<a[i]<<"->IsBalance?"<<t.IsBalance()<<endl;
    }

    cout<<"IsBalance?"<<t.IsBalance()<<endl;
    t.InOrder();
}


/***************************/
#include <iostream>
#include <windows.h>
using namespace std;
#include  "RBTree.h"

int main()
{
    TestRBTree();

    system("pause");
    return 0;
}

AVLTree:https://blog.csdn.net/Romantic_C/article/details/81262703

猜你喜欢

转载自blog.csdn.net/romantic_c/article/details/81263820