红黑树封装map和set

红黑树源代码

我们将由下列的KV模型红黑树来模拟封装STL库中的map和set

注意:为了实现封装map和set,我们需要对下列源码进行优化。

#pragma once
#include<iostream>
using namespace std;
//枚举类型的颜色分类
enum Colour
{
    RED,
    BLACK
};

//定义一个结构体结点
template<class K,class V>
struct RBTreeNode
{
    RBTreeNode<K, V>* _left;
    RBTreeNode<K, V>* _right;
    RBTreeNode<K, V>* _parent;
    pair<K, V> _kv;
    Colour _col;

    RBTreeNode(const pair<K, V>& kv)
        :_left(nullptr)
        , _right(nullptr)
        , _parent(nullptr)
        , _kv(kv)
        , _col(RED)
    {}
};

//红黑树类
template<class K, class V>
class RBTree
{
    typedef RBTreeNode<K, V> Node;
public:
    //中序遍历副函数
    void Inorder()
    {
        _Inorder(_root);
    }
    //中序遍历主函数
    void _Inorder(Node* root)
    {
        if (root == nullptr)
            return;
        _Inorder(root->_left);
        cout << root->_kv.first << " ";
        _Inorder(root->_right);
    }


    //插入函数
    bool insert(const pair<K, V>& kv)
    {
        //按照二叉树搜索树插入
        if (_root == nullptr)//根结点为空时new一个最初的根结点
        {
            _root = new Node(kv);
            _root->_col = BLACK;//根结点一定为黑
            return true;
        }
        Node* parent = nullptr;//这个为当前指针cur的父结点指针
        Node* cur = _root;//当前指针指向根
        while (cur)//当不为空,说明存在值,那么继续搜索可插入的地方
        {
            if (cur->_kv.first < kv.first)//key大于结点值,往右走
            {
                parent = cur;
                cur = cur->_right;
            }
            else if (cur->_kv.first > kv.first)//key小于结点值,往左走
            {
                parent = cur;
                cur = cur->_left;
            }
            else//相等,那么不插入,插入失败
            {
                return false;
            }
        }
        cur = new Node(kv);//新增结点
        cur->_col = RED;//默认红色
        //插入
        if (parent->_kv.first > kv.first)
        {
            parent->_left = cur;
            cur->_parent = parent;
        }
        else
        {
            parent->_right = cur;
            cur->_parent = parent;
        }
        //开始判断颜色
        while (parent != nullptr && parent->_col == RED)
        {
            Node* grandfather = parent->_parent;
            //如果父亲为红,那么违反红红规则,开始判断情况
            if (parent != nullptr && parent == grandfather->_left)
            {
                Node* uncle = grandfather->_right;//记录叔叔结点
                if (uncle != nullptr && uncle->_col == RED)//如果叔叔存在或者为红色,情况一
                {
                    //变色
                    parent->_col = uncle->_col = BLACK;//父亲和叔叔都变黑
                    grandfather->_col = RED;//爷爷变红

                    //将cur和parent往上移继续判断
                    cur = grandfather;
                    parent = cur->_parent;
                }
                else//叔叔不存在或者存在且为黑色,情况二和情况三结合
                {
                    if (cur == parent->_left)
                    {
                        RotateR(grandfather);//右旋
                        parent->_col = BLACK;
                        grandfather->_col = RED;
                    }
                    else
                    {
                        RotateLR(grandfather); //左右双旋
                        grandfather->_col = RED;
                        cur->_col = BLACK;
                    }
                    break;//根结点为黑,不需要往上了
                }
            }
            else//parent在grandfather的右边
            {
                Node* uncle = grandfather->_left;//记录叔叔结点
                if (uncle != nullptr && uncle->_col == RED)//如果叔叔存在或者为红色,情况一
                {
                    parent->_col = uncle->_col = BLACK;//父亲和叔叔都变黑
                    grandfather->_col = RED;//爷爷变红

                    //向上调整
                    cur = grandfather;
                    parent = grandfather->_parent;
                }
                else//叔叔不存在或者存在且为黑色,情况二和情况三结合
                {
                    if (cur == parent->_left)//如果插入在parent的左边
                    {
                        RotateRL(grandfather);//右左双旋
                        cur->_col = BLACK;
                        grandfather->_col = RED;

                    }
                    else//如果插入在parent的右边
                    {
                        RotateL(grandfather);//左旋
                        grandfather->_col = RED;
                        parent->_col = BLACK;
                    }
                    break;//根结点为黑,不需要往上了
                }
            }
        }
        _root->_col = BLACK;//往上移动后无论cur是否为根结点,统一为改黑

        return true;//插入成功

    }

    //左单旋
    void RotateL(Node* parent)
    {
        //定义新指针,方便操作
        Node* subR = parent->_right;
        Node* subRL = subR->_left;
        Node* pp = parent->_parent;//方便更改_root的操作

        parent->_right = subRL;//让parent结点链接subRL
        subR->_left = parent;//让subR的左子树链接parent
        parent->_parent = subR;//由于parent的_parent由nullptr变成了subR,所以也需要重新链接
        if (subRL)
            //判断subRL是否为空,如果为空的话就不需要对subRL进行操作了,不然会出现对空指针进行解引用的问题
        {
            subRL->_parent = parent;//不为空,那么让subRL链接parent
        }
        if (pp == nullptr)//如果parent是整棵树的根结点
        {
            _root = subR;//subR变为根结点
            subR->_parent = nullptr;//subR的_parent为空
        }
        else//如果parent不是整棵树的根结点,那么将新的parent重新链接上一个结点
        {
            if (pp->_left = parent)//如果parent是上一个结点的左子树,那么新的parent也是
            {
                pp->_left = subR;
            }
            else//如果parent是上一个结点的右子树,那么新的parent也是
            {
                pp->_right = subR;
            }
            subR->_parent = pp;//更新subR的父结点
        }
        //parent->_bf = subR->_bf = 0;//由于旋转后,整棵树的高度变回插入前的,那么此时parent和subR(cur)的因子都变回0
    }

    //右单旋
    void RotateR(Node* parent)
    {
        Node* subL = parent->_left;
        Node* subRR = subL->_right;
        Node* pp = parent->_parent;

        //建立subL和parent之间的关系
        parent->_left = subRR;
        subL->_right = parent;

        //建立parent和subRR之间的关系
        parent->_parent = subL;
        if (subRR != nullptr)
        {
            subRR->_parent = parent;
        }

        //建立PP和subL之间的关系
        if (pp == nullptr)
        {
            _root = subL;
            subL->_parent = nullptr;
        }
        else
        {
            if (pp->_left == parent)
            {
                pp->_left = subL;
            }
            else
            {
                pp->_right = parent;
            }
            subL->_parent = pp;
        }
        //更新平衡因子
        //subL->_bf = parent->_bf = 0;
    }

    //左右双旋
    void RotateLR(Node* parent)
    {
        Node* subL = parent->_left;
        Node* subLR = subL->_right;

        //int bf = subLR->_bf;

        RotateL(parent->_left);
        RotateR(parent);

        //if (bf == 0)
        //{
        //    //subLR自己就是新增
        //    subLR->_bf = 0;
        //    subL->_bf = 0;
        //    parent->_bf = 0;
        //}
        //else if (bf == -1)
        //{
        //    //subLR的左子树新增
        //    subLR->_bf = 0;
        //    subL->_bf = 0;
        //    parent->_bf = 1;
        //}
        //else if (bf == 1)
        //{
        //    //subLR的右子树新增
        //    subLR->_bf = 0;
        //    subL->_bf = -1;
        //    parent->_bf = 0;
        //}
        //else
        //{
        //    assert(false);
        //}
    }

    //右左双旋
    void RotateRL(Node* parent)
    {
        Node* subR = parent->_right;
        Node* subRL = subR->_left;
        //int bf = subRL->_bf;

        RotateR(parent->_right);
        RotateL(parent);

        //if (bf == 0)
        //{
        //    //subRL自己就是新增
        //    parent->_bf = subR->_bf = subRL->_bf = 0;
        //}
        //else if (bf == -1)
        //{
        //    //subRL的左子树新增
        //    parent->_bf = 0;
        //    subRL->_bf = 0;
        //    subR->_bf = 1;
        //}
        //else if (bf == 1)
        //{
        //    //subRL的右子树新增
        //    parent->_bf = -1;
        //    subRL->_bf = 0;
        //    subR->_bf = 0;
        //}
        //else
        //{
        //    assert(false);
        //}
    }

    // blacknum是根结点到当前结点的黑色结点数量
    bool check(Node* root,int blacknum,int count)
    {
        if (root == nullptr)
        {
            if(count != blacknum)
            {
                cout << "黑色结点数量不等" << endl;
                return false;
            }
            
            return true;
        }

        if (root->_col == RED && root->_parent->_col == RED)
        {
            cout << "有连续的红色结点" << endl;
            return false;
        }


        if (root->_col == BLACK)
        {
            ++blacknum;
        }

        return check(root->_left,blacknum,count) && check(root->_right,blacknum,count);
    }

    bool isbalance()
    {
        if (_root == nullptr)
        {
            return true;
        }
        if (_root->_col == RED)
        {
            return false;
        }
        //找最左路径作为黑色结点数目的参考值
        Node* cur = _root;
        int count = 0;
        while (cur)
        {
            if (cur->_col == BLACK)
                ++count;
            cur = cur->_left;
        }

        int blacknum = 0;
        return check(_root,blacknum,count); 
    }
private:
    Node* _root = nullptr;
};

红黑树的模板

首先,我们要知道,set是K模型,map是KV模型,那么如何用一颗红黑树同时封装出两种模型呢?这时候就应该想到模板了。

我们需要对红黑树类模板进行修改:

这是原始代码:

template<class K, class V>
class RBTree

 这是修改后的代码:

template<class K, class T, class KeyofT>
class RBTree

可以看到,这将V变为T,然后多出了KeyofT,这是什么意思呢?

class V    --->    class T

set是K模型,map是KV模型

在set容器中,T是对应着key:

    template<class K>
    class set
    {
    public:
    //...
    private:
        RBTree<K, K, SetKeyofT> _t;
    };

在map容器中,T是对应着key和value组成的键值对:

    template<class K,class V>
    class map
    {
    public:
    //...
    private:
        RBTree<K, pair<K, V>, MapKeyofT> _t;
    };

 

这时候会有一个疑问,能不能把第一个参数:class K 给去掉,因为在set中,K已经重复了;在map中,貌似键值对里也已经包含着key和value了?

可以肯定地说:不能去掉!在set中,确实可以省略不要;但是在map中,有些容器接口需要给出key的类型,那么在键值对中,我们只能取到key的值。所以在map中不能删去。

所以,我们更改了红黑树源码中的结点类实现

结点类实现

//定义一个结构体结点
template<class T>
struct RBTreeNode
{
    RBTreeNode<T>* _left;
    RBTreeNode<T>* _right;
    RBTreeNode<T>* _parent;

    T _data;
    Colour _col;

    RBTreeNode(const T& data)
        :_left(nullptr)
        , _right(nullptr)
        , _parent(nullptr)
        , _data(data)
        , _col(RED)
    {}
};

可以看到,这里的 T _data就是新增的,T对应set中的key,map中的键值对。

  map、set中的仿函数

class KeyofT

 在上述set和map容器的私有成员中,分别有着:

 在map和set分别传入底层红黑树时,T传入的可能是key,也可能是key和value的键值对,如果是键值对,那么就需要将键值对的key提取出来再进行比较,那么此时就需要用到仿函数。

map容器:

    template<class K,class V>
    class map
    {
    public:
        struct MapKeyofT
        {
            const K& operator()(const pair<K,V>& kv)
            {
                return kv.first;
            }
        };
    private:
        RBTree<K, pair<K, V>, MapKeyofT> _t;
    };

set容器:

    template<class K>
    class set
    {
    public:
        struct SetKeyofT
        {
            const K& operator()(const K& key)
            {
                return key;
            }
        };
    private:
        RBTree<K, K, SetKeyofT> _t;
    };

可以看到,我们在这个仿函数中重载了operator(), 这个operator()在map中用来提取kv.first,也就是key值,为了能统一map和set,我们在set也重载了operator()。

所以set传入底层红黑树就是set的仿函数,map传入底层红黑树就是map的仿函数。

那么应该怎么用呢?

例如在insert插入函数中,我们需要获取结点内的key值进行比较大小

新定义了一个kot:

KeyofT kot;

这是其中一小段代码:

if (kot(cur->_data) < kot(data))//key大于结点值,往右走

这里可以调用仿函数,如果_data/data类型是key,那么在仿函数中直接就返回key;如果类型是键值对,那么就返回kv.first

迭代器类实现

在迭代器中,解引用操作就是获取结点的数据的引用,->操作就是获取结点数据的地址即可。

真正有难度的是++和--:

在树中的++和--是按照中序遍历的方式进行的,也就是让指针按照 左子树-根-右子树 的顺序移动。

在++操作中:

如果右子树不为空,那么进入右子树然后寻找最左结点。

如果右子树为空,那么往上返回父亲节点,然后找到当前结点不是父亲结点的右子树的父亲节点。

在--操作中:

如果左子树不为空,那么进入右子树然后寻找最右结点。

如果左子树为空,那么往上返回父亲节点,然后找到当前结点不是父亲结点的左子树的父亲节点。

//迭代器类
template<class T, class Ref,class Ptr>
struct _TreeIterator
{
    typedef RBTreeNode<T> Node;//结点类型
    typedef _TreeIterator<T, Ref, Ptr> Self;
    Node* _node;//结点指针

    //构造函数
    _TreeIterator(Node* node)
        :_node(node)
    {}

    Ref operator*()
    {
        return _node->_data;//返回结点数据的引用
    }

    Ptr operator->()
    {
        return &_node->_data;//返回结点数据的地址
    }

    Self operator++()
    {
        if (_node->_right)//如果右子树存在
        {
            Node* cur = _node->_right;//则进入右子树
            while (cur->_left)//找到右子树的最左结点
            {
                cur = cur->_left;
            }
            _node = cur;//更新当前结点
        }
        else//如果右子树不存在
        {
            Node* cur = _node;
            Node* parent = cur->_parent;
            while (parent && cur == parent->_right)//父亲结点存在且当前结点为父亲结点的右子树
            {
                //不断往上循环
                cur = parent;
                parent = parent->_parent;
            }
            //当前结点不是父亲的右子树时,更新指针指向当前结点的父亲结点
            _node = parent;
        }
        return *this;
    }


    Self operator--()
    {
        if (_node->_left) //结点的左子树不为空
        {
            //寻找该结点左子树当中的最右结点
            Node* right = _node->_left;
            while (right->_right)
            {
                right = right->_right;
            }
            _node = right; //--后变为该结点
        }
        else //结点的左子树为空
        {
            //寻找孩子不在父亲左的祖先
            Node* cur = _node;
            Node* parent = cur->_parent;
            while (parent && cur == parent->_left)
            {
                cur = parent;
                parent = parent->_parent;
            }
            _node = parent; //--后变为该结点
        }
        return *this;
    }


    bool operator!=(const Self& s) const
    {
        return _node != s._node; //判断两个正向迭代器所封装的结点是否是同一个
    }

	bool operator==(const Self& s) const
	{
		return _node == s._node; //判断两个正向迭代器所封装的结点是否是同一个
	}
};

迭代器函数实现 

在树中的begin()和end()也有着不同的规则:

begin()获取的是树的最左结点。

end()获取的是树的最右结点的后一个结点,也就是空结点。

    //迭代器函数
    typedef _TreeIterator<T,T&,T*> iterator;
    typedef _TreeIterator<T, const T&, const T*> const_iterator;
    iterator begin()
    {
        Node* cur = _root;
        while (cur && cur->_left)//寻找最左结点
        {
            cur = cur->_left;
        }

        return iterator(cur);
    }
    iterator end()
    {
        return iterator(nullptr);
    }

    const_iterator begin() const
    {
        Node* cur = _root;
        while (cur && cur->_left)//寻找最左结点
        {
            cur = cur->_left;
        }

        return iterator(cur);
    }
    const_iterator end() const
    {
        return iterator(nullptr);
    }

优化后的红黑树源码

#pragma once
#include<iostream>
using namespace std;
//枚举类型的颜色分类
enum Colour
{
    RED,
    BLACK
};

//定义一个结构体结点
template<class T>
struct RBTreeNode
{
    RBTreeNode<T>* _left;
    RBTreeNode<T>* _right;
    RBTreeNode<T>* _parent;

    T _data;
    Colour _col;

    RBTreeNode(const T& data)
        :_left(nullptr)
        , _right(nullptr)
        , _parent(nullptr)
        , _data(data)
        , _col(RED)
    {}
};

//迭代器类
template<class T, class Ref,class Ptr>
struct _TreeIterator
{
    typedef RBTreeNode<T> Node;
    typedef _TreeIterator<T, Ref, Ptr> Self;
    Node* _node;

    _TreeIterator(Node* node)
        :_node(node)
    {}

    Ref operator*()
    {
        return _node->_data;
    }

    Ptr operator->()
    {
        return &_node->_data;
    }

    Self operator++()
    {
        if (_node->_right)
        {
            Node* cur = _node->_right;
            while (cur->_left)
            {
                cur = cur->_left;
            }
            _node = cur;
        }
        else
        {
            Node* cur = _node;
            Node* parent = cur->_parent;
            while (parent && cur == parent->_right)
            {
                cur = parent;
                parent = parent->_parent;
            }
            _node = parent;
        }
        return *this;
    }

    Self operator--()
    {
        if (_node->_left) //结点的左子树不为空
        {
            //寻找该结点左子树当中的最右结点
            Node* right = _node->_left;
            while (right->_right)
            {
                right = right->_right;
            }
            _node = right; //--后变为该结点
        }
        else //结点的左子树为空
        {
            //寻找孩子不在父亲左的祖先
            Node* cur = _node;
            Node* parent = cur->_parent;
            while (parent && cur == parent->_left)
            {
                cur = parent;
                parent = parent->_parent;
            }
            _node = parent; //--后变为该结点
        }
        return *this;
    }

    bool operator!=(const Self& s) const
    {
        return _node != s._node; //判断两个正向迭代器所封装的结点是否是同一个
    }
};


//红黑树类
template<class K, class T, class KeyofT>
class RBTree
{
    typedef RBTreeNode<T> Node;
public:
    //中序遍历副函数
    void Inorder()
    {
        _Inorder(_root);
    }
    //中序遍历主函数
    void _Inorder(Node* root)
    {
        if (root == nullptr)
            return;
        _Inorder(root->_left);
        cout << root->_kv.first << " ";
        _Inorder(root->_right);
    }

    //迭代器函数
    typedef _TreeIterator<T,T&,T*> iterator;
    typedef _TreeIterator<T, const T&, const T*> const_iterator;
    iterator begin()
    {
        Node* cur = _root;
        while (cur && cur->_left)
        {
            cur = cur->_left;
        }

        return iterator(cur);
    }
    iterator end()
    {
        return iterator(nullptr);
    }

    const_iterator begin() const
    {
        Node* cur = _root;
        while (cur && cur->_left)
        {
            cur = cur->_left;
        }

        return iterator(cur);
    }
    const_iterator end() const
    {
        return iterator(nullptr);
    }


    //插入函数
    pair<iterator,bool> insert(const T& data)
    {
        //按照二叉树搜索树插入
        if (_root == nullptr)//根结点为空时new一个最初的根结点
        {
            _root = new Node(data);
            _root->_col = BLACK;//根结点一定为黑
            return make_pair(iterator(_root),true);
        }
        Node* parent = nullptr;//这个为当前指针cur的父结点指针
        Node* cur = _root;//当前指针指向根
        KeyofT kot;

        while (cur)//当不为空,说明存在值,那么继续搜索可插入的地方
        {
            if (kot(cur->_data) < kot(data))//key大于结点值,往右走
            {
                parent = cur;
                cur = cur->_right;
            }
            else if (kot(cur->_data) > kot(data))//key小于结点值,往左走
            {
                parent = cur;
                cur = cur->_left;
            }
            else//相等,那么不插入,插入失败
            {
                return make_pair(iterator(cur), false);
            }
         }
        cur = new Node(data);//新增结点
        Node* newnode = cur;
        cur->_col = RED;//默认红色
        //插入
        if (kot(parent->_data) > kot(data))
        {
            parent->_left = cur;
            cur->_parent = parent;
        }
        else
        {
            parent->_right = cur;
            cur->_parent = parent;
        }
        //开始判断颜色
        while (parent != nullptr && parent->_col == RED)
        {
            Node* grandfather = parent->_parent;
            //如果父亲为红,那么违反红红规则,开始判断情况
            if (parent != nullptr && parent == grandfather->_left)
            {
                Node* uncle = grandfather->_right;//记录叔叔结点
                if (uncle != nullptr && uncle->_col == RED)//如果叔叔存在或者为红色,情况一
                {
                    //变色
                    parent->_col = uncle->_col = BLACK;//父亲和叔叔都变黑
                    grandfather->_col = RED;//爷爷变红

                    //将cur和parent往上移继续判断
                    cur = grandfather;
                    parent = cur->_parent;
                }
                else//叔叔不存在或者存在且为黑色,情况二和情况三结合
                {
                    if (cur == parent->_left)
                    {
                        RotateR(grandfather);//右旋
                        parent->_col = BLACK;
                        grandfather->_col = RED;
                    }
                    else
                    {
                        RotateLR(grandfather); //左右双旋
                        grandfather->_col = RED;
                        cur->_col = BLACK;
                    }
                    break;//根结点为黑,不需要往上了
                }
            }
            else//parent在grandfather的右边
            {
                Node* uncle = grandfather->_left;//记录叔叔结点
                if (uncle != nullptr && uncle->_col == RED)//如果叔叔存在或者为红色,情况一
                {
                    parent->_col = uncle->_col = BLACK;//父亲和叔叔都变黑
                    grandfather->_col = RED;//爷爷变红

                    //向上调整
                    cur = grandfather;
                    parent = grandfather->_parent;
                }
                else//叔叔不存在或者存在且为黑色,情况二和情况三结合
                {
                    if (cur == parent->_left)//如果插入在parent的左边
                    {
                        RotateRL(grandfather);//右左双旋
                        cur->_col = BLACK;
                        grandfather->_col = RED;

                    }
                    else//如果插入在parent的右边
                    {
                        RotateL(grandfather);//左旋
                        grandfather->_col = RED;
                        parent->_col = BLACK;
                    }
                    break;//根结点为黑,不需要往上了
                }
            }
        }
        _root->_col = BLACK;//往上移动后无论cur是否为根结点,统一为改黑

        return make_pair(iterator(newnode), true);//插入成功

    }

    //左单旋
    void RotateL(Node* parent)
    {
        //定义新指针,方便操作
        Node* subR = parent->_right;
        Node* subRL = subR->_left;
        Node* pp = parent->_parent;//方便更改_root的操作

        parent->_right = subRL;//让parent结点链接subRL
        subR->_left = parent;//让subR的左子树链接parent
        parent->_parent = subR;//由于parent的_parent由nullptr变成了subR,所以也需要重新链接
        if (subRL)
            //判断subRL是否为空,如果为空的话就不需要对subRL进行操作了,不然会出现对空指针进行解引用的问题
        {
            subRL->_parent = parent;//不为空,那么让subRL链接parent
        }
        if (pp == nullptr)//如果parent是整棵树的根结点
        {
            _root = subR;//subR变为根结点
            subR->_parent = nullptr;//subR的_parent为空
        }
        else//如果parent不是整棵树的根结点,那么将新的parent重新链接上一个结点
        {
            if (pp->_left = parent)//如果parent是上一个结点的左子树,那么新的parent也是
            {
                pp->_left = subR;
            }
            else//如果parent是上一个结点的右子树,那么新的parent也是
            {
                pp->_right = subR;
            }
            subR->_parent = pp;//更新subR的父结点
        }
        //parent->_bf = subR->_bf = 0;//由于旋转后,整棵树的高度变回插入前的,那么此时parent和subR(cur)的因子都变回0
    }




    //右单旋
    void RotateR(Node* parent)
    {
        Node* subL = parent->_left;
        Node* subRR = subL->_right;
        Node* pp = parent->_parent;

        //建立subL和parent之间的关系
        parent->_left = subRR;
        subL->_right = parent;

        //建立parent和subRR之间的关系
        parent->_parent = subL;
        if (subRR != nullptr)
        {
            subRR->_parent = parent;
        }

        //建立PP和subL之间的关系
        if (pp == nullptr)
        {
            _root = subL;
            subL->_parent = nullptr;
        }
        else
        {
            if (pp->_left == parent)
            {
                pp->_left = subL;
            }
            else
            {
                pp->_right = parent;
            }
            subL->_parent = pp;
        }
        //更新平衡因子
        //subL->_bf = parent->_bf = 0;
    }



    //左右双旋
    void RotateLR(Node* parent)
    {
        Node* subL = parent->_left;
        Node* subLR = subL->_right;

        //int bf = subLR->_bf;

        RotateL(parent->_left);
        RotateR(parent);

        //if (bf == 0)
        //{
        //    //subLR自己就是新增
        //    subLR->_bf = 0;
        //    subL->_bf = 0;
        //    parent->_bf = 0;
        //}
        //else if (bf == -1)
        //{
        //    //subLR的左子树新增
        //    subLR->_bf = 0;
        //    subL->_bf = 0;
        //    parent->_bf = 1;
        //}
        //else if (bf == 1)
        //{
        //    //subLR的右子树新增
        //    subLR->_bf = 0;
        //    subL->_bf = -1;
        //    parent->_bf = 0;
        //}
        //else
        //{
        //    assert(false);
        //}
    }

    //右左双旋
    void RotateRL(Node* parent)
    {
        Node* subR = parent->_right;
        Node* subRL = subR->_left;
        //int bf = subRL->_bf;

        RotateR(parent->_right);
        RotateL(parent);

        //if (bf == 0)
        //{
        //    //subRL自己就是新增
        //    parent->_bf = subR->_bf = subRL->_bf = 0;
        //}
        //else if (bf == -1)
        //{
        //    //subRL的左子树新增
        //    parent->_bf = 0;
        //    subRL->_bf = 0;
        //    subR->_bf = 1;
        //}
        //else if (bf == 1)
        //{
        //    //subRL的右子树新增
        //    parent->_bf = -1;
        //    subRL->_bf = 0;
        //    subR->_bf = 0;
        //}
        //else
        //{
        //    assert(false);
        //}
    }

    // blacknum是根结点到当前结点的黑色结点数量
    bool check(Node* root, int blacknum, int count)
    {
        if (root == nullptr)
        {
            if (count != blacknum)
            {
                cout << "黑色结点数量不等" << endl;
                return false;
            }

            return true;
        }

        if (root->_col == RED && root->_parent->_col == RED)
        {
            cout << "有连续的红色结点" << endl;
            return false;
        }


        if (root->_col == BLACK)
        {
            ++blacknum;
        }

        return check(root->_left, blacknum, count) && check(root->_right, blacknum, count);
    }

    bool isbalance()
    {
        if (_root == nullptr)
        {
            return true;
        }
        if (_root->_col == RED)
        {
            return false;
        }
        //找最左路径作为黑色结点数目的参考值
        Node* cur = _root;
        int count = 0;
        while (cur)
        {
            if (cur->_col == BLACK)
                ++count;
            cur = cur->_left;
        }

        int blacknum = 0;
        return check(_root, blacknum, count);
    }
private:
    Node* _root = nullptr;
};

用红黑树封装set的容器

#pragma once
#include"RBTree.h"

namespace bear
{
    template<class K>
    class set
    {
    public:
        //仿函数
        struct SetKeyofT
        {
            const K& operator()(const K& key)
            {
                return key;
            }
        };
        //红黑树最好不要修改,将普通迭代器和const迭代器都用const迭代器重命名
        typedef typename RBTree<K, K, SetKeyofT>::const_iterator iterator;
        typedef typename RBTree<K, K, SetKeyofT>::const_iterator const_iterator;

        iterator begin() const
        {
            return _t.begin();
        }
        iterator end() const
        {
            return _t.end();
        }

        pair<iterator, bool> Insert(const K& key)
        {
            return _t.insert(key);
        }

    private:
        RBTree<K, K, SetKeyofT> _t;
    };
}

 用红黑树封装map的容器

在map中,还需要对[]运算符进行重载。

#pragma once
#include"RBTree.h"

namespace bear
{
    template<class K,class V>
    class map
    {
    public:
        struct MapKeyofT
        {
            const K& operator()(const pair<K,V>& kv)
            {
                return kv.first;
            }
        };

        typedef typename RBTree<K, pair<K, V>, MapKeyofT>::iterator iterator;

        iterator begin()
        {
            return _t.begin();
        }
        iterator end()
        {
            return _t.end();
        }

        V& operator[](const K& key)
        {
            pair<iterator, bool> ret = insert(make_pair(key, V()));
            return ret.first->second;
        }

        pair<iterator, bool> Insert(const pair<K, V>& kv)
        {
            return _t.insert(kv);
        }
    private:
        RBTree<K, pair<K, V>, MapKeyofT> _t;
    };
}

  • 20
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值