C++实现红黑树

红黑树简介

红黑树是一个高效的平衡搜索树,保证最长路径不超过最短路径的两倍,因而近似平衡,保证了高度,也就保证了效率。增删查改时间复杂度都是O(logN)

性质:

  1. 每个结点不是红色就是黑色的。
  2. 根结点是黑色的。
  3. 如果一个结点是红色的,则它的两个子节点是黑色的(没有连续的红结点)
  4. 对于每个结点,从该结点到其所有后代叶节点的简单路径上,均包含相同数目的黑色结点(每条路径的黑色节点的数目相等
  5. 每个叶子结点都为黑色(此处叶子结点是空结点)

这几条规则保证了红黑树最长路径不超过最短路径的两倍(给个极端情况全黑色,然后在结点之间插入红色结点,即可得到结论)

结点的实现

三叉链实现RBtree,用KV存储结构,最后用枚举包含了相应的颜色。

树的实现

共有成员为空的构造函数,插入函数
私有成员为根,

红黑树的插入

为什么插入结点的颜色为红色好?
如果插入结点为黑色首先违背了第四条规则,每条路径黑色结点数目相同,虽然可以调整但是难调,我们原则上的保持第四条规则,所以选择插入红色节点。

方法:
首先判断是否为空树,接着找到插入结点,根据插入结点的情况来调整。 cur为插入结点,g为组父节点,p是父亲结点,u是叔叔结点
1. 如果插入结点为根结点,则直接插入,并且将根结点赋值为黑色。
2. 如果插入结点的父节点为黑色结点,那么直接插入。
3. 如果插入结点的父节点为红色结点,那么再次插入时,必然会有两个红色结点相连接,此时需要调整。

叔叔结点的情况和调整有关,叔叔的情况有以下几种:
叔叔存在且为红色
叔叔不存在
叔叔为黑色

插入分为三种情况

  1. 组父节点为黑色,父节点和叔叔结点为为红色,插入节点的为红色。
    此种情况下父亲结点和叔叔结点变为黑色,祖父结点变为红色,如果祖父结点是根结点则不影响,如果祖父结点不是根结点,则需要向上更新,
  2. 祖父结点为黑色,父亲结点为红色,叔叔结点(不存在或者为黑色),插入结点为红色。(单旋)

    • 第一种情况,叔叔不存在,cur为新增结点,
    • 第二种情况,叔叔存在且为黑色,parent的一边C一定存在且为黑色,cur为红色结点,cur此时不是新插入的结点,cur存在左右孩子,并且cur原先为黑色((cur此时左右为黑色吗?))

此时旋转来调整结点,观察p和cur均为左孩子,此时右单旋,p和cur均为右孩子,此时左单旋。

  1. 祖父结点为黑色,父亲结点为红色,叔叔结点(不存在或者为黑色),插入结点为红色。(双旋)
    • 第一种情况:u存在并且一定为黑色,cur不是新插入的结点,cur存在左右孩子,并且cur原先为黑色。
    • 第二种情况:u不存在,cur一定为新插入的结点。

实现代码如下

#include <iostream>
#include <assert.h>
using namespace std;

enum Colour
{
    RED,
    BLACK,
};

template <class K,class V>
struct RBTreeNode
{
    RBTreeNode* _left;
    RBTreeNode* _right;
    RBTreeNode* _parent;

    K _key;
    V _value;

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

template <class K,class V>
class RBTree
{
    typedef RBTreeNode<K, V> Node;
public:
    RBTree()
        :_root(NULL)
    {}
    ~RBTree()
    {
        //if (_root)
        //  _root = _Destroy(_root);
    }
    RBTree(const RBTree<K, V>& rb)
    {
        if (this != &rb)
            _root = _Copy(_root);
    }
    RBTree<K, V> operator=(const RBTree<K, V>& rb)
    {
        if (*this != rb)
        {
            Node* tmp = _Copy(rb->_root);
            _root = _Destroy(_root);
            _root = tmp;
        }
        return *this;
    }
    bool Insert(const K& key, const V& value)
    {
        if (_root == NULL)
        {
            _root = new Node(key, value);
            _root->_col = BLACK;
            return true;
        }
        Node* pCur = _root;
        Node* pParent = NULL;
        while (pCur)
        {
            if (key < pCur->_key)
            {
                pParent = pCur;
                pCur = pCur->_left;
            }
            else if (key > pCur->_key)
            {
                pParent = pCur;
                pCur = pCur->_right;
            }
            else
                return false;
        }
        pCur = new Node(key, value);
        if (key < pParent->_key)
            pParent->_left = pCur;
        else
            pParent->_right = pCur;
        pCur->_parent = pParent;
        //未调整到根节点且父节点还是红色
        while (pCur != _root && pParent->_col == RED)
        {
            Node* grandfather = pParent->_parent;
            //先处理左边
            if (grandfather->_left == pParent)
            {
                Node* uncle = pParent->_right;
                //叔叔存在且为红色
                if (uncle && uncle->_col == RED)
                {
                    pParent->_col = uncle->_col = BLACK;
                    grandfather->_col = RED;
                    pCur = grandfather;
                    pParent = pCur->_parent;
                }
                //叔叔不存在或者叔叔为黑色
                else
                {
                    //pCur为pParent的右孩子
                    if (pParent->_right == pCur)
                    {
                        RotateL(pParent);
                        std::swap(pCur, pParent);
                    }
                    //pCur为pParent的左孩子
                    else
                    {
                        RotateR(grandfather);
                        grandfather->_col = RED;
                        pParent->_col = BLACK;
                    }
                }
            }
            //再处理右边的情况(与上述情况刚好位置相反)
            else
            {
                Node* uncle = grandfather->_left;
                //叔叔存在且为红
                if (uncle && uncle->_col == RED)
                {
                    pParent->_col = uncle->_col = BLACK;
                    pCur->_col = RED;
                    pCur = grandfather;
                    pParent = pCur->_parent;
                }
                //叔叔不存在或者叔叔为黑色
                else
                {
                    //pCur为pParent的左孩子
                    if (pParent->_left == pCur)
                    {
                        RotateR(pParent);
                        std::swap(pCur, grandfather);
                    }
                    //pCur为pParent的右孩子
                    else
                    {
                        RotateL(grandfather);
                        grandfather->_col = RED;
                        pParent->_col = BLACK;
                    }
                }
            }
        }
        _root->_col = BLACK;
        return true;
    }


    void RotateR(Node* parent)
    {
        assert(parent);
        Node* subL = parent->_left;
        Node* subLR = subL->_right;
        parent->_left = subLR;
        if (subLR)
            subLR->_parent = parent;
        Node* pparent = parent->_parent;
        subL->_right = parent;
        parent->_parent = subL;
        if (pparent->_left == parent)
        {
            pparent->_left = subL;
            subL->_parent = pparent;
        }
        else if (pparent->_right == parent)
        {
            pparent->_right = subL;
            subL->_parent = pparent;
        }
        else
        {
            _root = subL;
            subL->_parent = NULL;
        }
    }
    void RotateL(Node* parent)
    {
        assert(parent);
        Node* subR = parent->_right;
        Node* subRL = subR->_left;

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

        Node* pparent = parent->_parent;
        subR->_left = parent;
        parent->_parent = subR;
        if (pparent->_left = subR->_parent)
        {
            pparent->_left = subR;
            subR->_parent = pparent;
        }
        else if (pparent->_right = subR->_parent)
        {
            pparent->_right = subR;
            subR->_parent = pparent;
        }
        else
        {
            _root = subR;
            subR->_parent = NULL;
        }
    }
    bool IsBalance()
    {
        if (NULL == _root)
            return true;
        if (_root->_col == RED)
            return false;
        size_t count = 0;
        Node* cur = _root;
        while (cur)
        {
            if (cur->_col == BLACK)
                count++;
            cur = cur->_left;
        }
        size_t k = 0;
        _IsBalance(_root, count, k);
    }
    void InOrder()
    {
        _Inorder(_root);
        cout << endl;
    }


private:
    bool _IsBalance(Node* _root, size_t count, size_t k)
    {
        if (_root == NULL)
            return true;
        if (_root->_parent&&_root->_col == _root->_parent->_col == RED)
            return false;
        if (_root->_col == BLACK)
            k++;
        if (_root->_left == NULL&&_root->_right == NULL)
        {
            if (count == k)
                return true;
            else
                return false;
        }
        return ((_IsBalance(_root->_left, count, k))&&(_IsBalance(_root->_right, count, k)));
    }
    void _Inorder(Node* Root)
    {
        if (Root)
        {
            _Inorder(Root->_left);
            cout << Root->_key << endl;
            _Inorder(Root->_right);
        }
    }
    Node* _Copy(Node* pRoot)
    {
        Node* pCur = pRoot;
        if (pCur)
        {
            pCur = new Node(pRoot->_key, pRoot->_value);
            pCur->_left= _Copy(pRoot->_left);
            pCur->_right = _Copy(pRoot->_right);
        }
        return pCur;
    }
    //销毁
    Node* _Destory(Node* pRoot)
    {
        if (pRoot)
        {
            pRoot->_left = _Destory(pRoot->_left);
            pRoot->_right = _Destory(pRoot->_right);
            delete pRoot;
            pRoot = NULL;
        }
        return pRoot;
    }
    Node* _root;
};

测试文件:

#include "RBtree.h"
using namespace std;
void test()
{
    RBTree<int, int> rb;
    int arr[] = { 10, 7, 8, 15, 5, 6, 11, 13, 12 };
    for (size_t idx = 0; idx < sizeof(arr) / sizeof(arr[0]); ++idx)
    {
        rb.Insert(arr[idx], idx);
    }
    rb.InOrder();
    if (rb.IsBalance())
        cout << "是红黑树." << endl;
    else
        cout << "不是红黑树." << endl;
    rb.InOrder();

}

int main()
{
    test();
    system("pause");
    return 0;
}

红黑树的应用

红黑树是一颗高效的二叉搜索树,用途很广,例如STL中set\map\unorder_map\unorder_set都运用到了红黑树。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值