【数据结构】:红黑树(RB Tree)

红黑树是近似平衡的二叉搜索树。
红黑树的性质:
1,每个节点不是红色就是黑色
2,根节点必须是黑色
3,没有连续的红节点
4,每条路径上黑色节点数目相等

红黑树保证最长路径不超过最短路径的两倍。那么,为什么满足以上这些条件就能保证呢?
最短路径一定是节点全黑,要保证每条路径的黑节点数量相等,只能在两个黑节点之间添加红节点,所以最长路径不会超过最短路径的两倍。
红黑树保证效率为log2^N

这里写图片描述

如上图所示是一棵简单的红黑树,红黑树的插入要通过旋转和变色来调节平衡。

当parent是grandfather的左孩子,uncle是grandfather的右孩子时,插入可分为以下情况:

1,叔叔节点存在且为红色
这里写图片描述

这里写图片描述

Node* grandfther = parent->_parent;
            if (parent == grandfther->_left)
            {
                Node* uncle = grandfther->_right;
                if (uncle && uncle->_col == RED)
                {
                    parent->_col = BLACK;
                    uncle->_col = BLACK;
                    grandfther->_col = RED;

                    cur = grandfther;
                    parent = cur->_parent;
                }

2,叔叔节点不存在或存在且为黑
这里写图片描述

将parent变黑,grandfather变红,进行右单旋
这里写图片描述

else // u 不存在 u黑
                {
                    if(cur == parent->_right) // 双旋
                    {
                        RotateL(parent);
                        swap(cur,parent);
                    }

                    RotateR(grandfther);
                    parent->_col = BLACK;
                    grandfther->_col = RED;
                    break;
                }

3,cur是parent的右孩子,需要双旋
这里写图片描述

当parent是grandfather的右时,需要分析的情况还是以上三种,只是方向相反而已。

完整代码:

#pragma once
#include<iostream>
using namespace std;

enum Colour
{
    RED,
    BLACK,
};

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

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

    Colour _col;

    RBTreeNode(const K& key, const V& value)
        :_key(key)
        , _value(value)
        , _left(NULL)
        , _right(NULL)
        , _parent(NULL)
        , _col(RED)
    {}
};


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

    RBTree(const RBTree<K, V>& tree)
    {
        _Copy(tree._root);
    }


    ~RBTree()
    {
        _Destroy(_root);
    }

    RBTree<K, V>& operator = (const RBTree<K, V>& tree)
    {
        RBTree<K, V> tmp(tree);
        swap(_root, tree._root);
        return *this;
    }


    bool Insert(const K& key, const V& value)
    {
        if (_root == NULL)
        {
            _root = new Node(key, value);
            _root->_col = 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 = new Node(key, value);
        if (parent->_key < key)
        {
            parent->_right = cur;
            cur->_parent = parent;
        }
        else
        {
            parent->_left = cur;
            cur->_parent = parent;
        }

        while (parent && parent->_col == RED)
        {
            Node* grandfather = parent->_parent;
            if (parent == grandfather->_left)
            {
                Node* uncle = grandfather->_right;
                if (uncle && uncle->_col == RED)
                {
                    parent->_col = BLACK;
                    uncle->_col = BLACK;
                    grandfather->_col = RED;

                    cur = grandfather;
                    parent = cur->_parent;
                }
                else // u 不存在 u黑
                {
                    if (cur == parent->_right) // 双旋
                    {
                        RotateL(parent);
                        swap(cur, parent);
                    }

                    RotateR(grandfather);
                    parent->_col = BLACK;
                    grandfather->_col = RED;
                    break;
                }
            }
            //parent = grandfather->right
            else if (parent == grandfather->_right)
            {
                Node* uncle = grandfather->_left;
                if (uncle && uncle->_col == RED)
                {
                    parent->_col = BLACK;
                    uncle->_col = BLACK;
                    grandfather->_col = RED;

                    cur = grandfather;
                    parent = cur->_parent;
                }
                else
                {
                    if (cur == parent->_right)
                    {
                        RotateR(parent);
                        swap(parent, cur);
                    }
                    RotateL(grandfather);
                    parent->_col = BLACK;
                    grandfather->_col = RED;
                    break;
                }
            }
        }
        _root->_col = BLACK;
        return true;
    }

    void InOrder()
    {
        _InOrder(_root);
    }

    bool IsBalance()
    {
        Node* cur = _root;
        if (_root == NULL)
        {
            return true;
        }
        //根节点是黑色
        if (_root->_col == RED)
        {
            return false;
        }
        int BlackNode = 0;
        //统计最左路径上黑色节点的数量
        while (cur)
        {
            if (cur->_col == BLACK)
            {
                ++BlackNode;
            }
            cur = cur->_left;
        }
        //一条路径上黑色节点的数量
        int num = 0;
        return _IsBlance(_root, BlackNode, num);
    }
protected:
    void _Copy(Node* root)
    {
        Node* newNode = NULL;
        Node* cur = root;
        while (cur)
        {
            newNode = new Node(cur->_key, cur->_value);
            newNode->_left = _Copy(cur->_left);
            newNode->_right = _Copy(cur->_right);
        }
    }

    void _Destroy(Node* root)
    {
        Node* cur = root;
        if (root == NULL)
            return;
        _Destroy(cur->_left);
        _Destroy(cur->_right);
        delete cur;
        cur = NULL;
    }


    bool _IsBlance(Node* root, const int BlackNode, int num)
    {
        //一条路径已经走完
        if (root == NULL)
        {
            if (num != BlackNode)
            {
                cout << "黑色节点数量不相等" << endl;
                return false;
            }
            else
            {
                return true;
            }
        }
        if (root->_col == BLACK)
        {
            ++num;
        }
        if((root->_col == RED) && (root->_parent) && (root->_parent->_col == RED))
        {
            cout << "有连续的红节点" << root->_key << endl;
            return false;
        }
        return _IsBlance(root->_left, BlackNode, num)
            && _IsBlance(root->_right, BlackNode, num);
    }

    //右旋
    void RotateR(Node* parent)
    {
        Node* subL = parent->_left;
        Node* subLR = subL->_right;
        parent->_left = subLR;
        if (subLR)
            subLR->_parent = parent;

        subL->_right = parent;
        Node* ppNode = parent->_parent;
        parent->_parent = subL;

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

    //左旋
    void RotateL(Node* parent)
    {
        Node* subR = parent->_right;
        Node* subRL = subR->_left;

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

        subR->_left = parent;
        Node* ppNode = parent->_parent;
        parent->_parent = subR;

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

    void _InOrder(Node* root)
    {
        Node* cur = root;
        if (cur == NULL)
            return;
        _InOrder(cur->_left);
        cout << cur->_key << " ";
        _InOrder(cur->_right);
    }
private:
    Node* _root;
};

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

我们知道,红黑树是近似平衡的二叉树,那么为什么不直接使用平衡二叉树呢?
原因是红黑树最坏的情况也是log2^N,但它不像平衡二叉树需要严格控制平衡因子,红黑树只需控制节点的颜色,因此它的旋转次数相对于平衡二叉树能少一些,因此,实际中,红黑树的应用更为广泛。

红黑树的应用:
1. C++ STL库 – map
2. Java 库
3. linux内核
4. 其他一些库

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值