STL库的实现方式
map和set的底层用的红黑树是一样的吗?从容器特点的角度出发,这里个容器的底层应该分别用key搜索模型的红黑树和key value 搜索模型的红黑树。但是,从库的设计角度出发,这两者用同一份红黑树代码更好。而STL就是用的同样一份key value 搜索模型的红黑树进行对map和set的封装的。下面就通过STL库的源码来简单看一看。

 可以看到,STL库里set也是用key vlaue搜索模型的红黑树。这颗红黑树的key存的是key,value存的也是key。下面再看看map。
 
 通过上图可以看到,库里面的map的底层用的也是一样的红黑树。不同的是这颗红黑树的value存的是一个pair结构。为什么这么设计呢?那就再往深层次谈一谈,我们下面就看看库里面的红黑树是怎么设计的。

 可以看到rb_tree是通过Value模版去实例化树的节点的。set传的Value是Key,底层__rb_tree_node类实例化的就是key的树。map传的Value是pair,底层__rb_tree_node类实例化的就是key value的树。这里的__rb_tree_node的就像一个适配器,上层传什么模板的Value,底层就对应实例化不同的节点。
虽然set和map的模板参数一样,都是Key Value。由于Value传的类型不一样,底层红黑树实例化也是不一样的。所以,本质上map和set用的不是同一颗红黑树,而是使用的同一份红黑树的模板。
那为什么还需要Key这个模板呢?在find和erase接口中还需要这个类型。
模拟实现map和set
我们现将红黑树的代码进行一下调整,将原来Key Value 的模板改成库里面的那样。然后类似于库里的map和set先把类模板和类成员基本的框架搭出来。
 
引入第三个模板参数来获取T的key
下面调整一下红黑树的插入接口。
 
通过上图看,在修改后的代码在比较逻辑上面会有问题。如果是map的话,这里的T就是一个pair,而pair的比较不符合实际用key来比较的需求。解决的方式就是用仿函数来处理,这里的仿函数和在优先级队列那里设计的方式又有区别。这里的仿函数用于将pair中key对象取出来。方便我们在需要用key进行比较的场景使用。
下面需要给红黑树再添加一个模板参数,然后分别在map和set内部实现一个仿函数

从这里就不得不佩服大佬设计数据结构的思路了。通过学习大佬前辈们在库里面的实现思路,不得不为大佬对于泛型编程水平折服。通过加一个模板,对map设计一个仿函数就可以达到通过T获取Key对象,这里set其实是被map稍稍拖了下后腿,不过问题不大。
迭代器的模拟实现
先以set为例讲解一下迭代器的实现思路,首先是迭代器的设计,这里使用T一个模板参数就能满足map和set的需求了。迭代器基础功能的实现这里不做过多讲解。重点需要理解的是operator++的重载。

 上图中的set在用红黑树的迭代器时,用typename是告诉编译器这是一个类型。
为了让我们简易版本的迭代器能跑起来,还需要实现operator++的重载。根据搜索二叉树的性质可知,当树进行中序遍历时,值是有序的。那么起始位置就是最小的值所在的节点。其实就是从根节点出发,树的最左子树。
那如何访问下一个节点呢?这要分两类情况讨论。
 情况一:当前节点右子树存在,就去访问右子树的最小节点。
 
 情况二 当前节点的右子树为空,去访问孩子是父亲左边的祖先。
 
 情况二又可以细分下面两种情况,分别是当前节点在父亲节点的左边和右边。若当前节点在父亲的左边,直接将修改当前节点值为当前节点的父节点即可。若当前节点是父亲的右子树,则需要向上遍历,直到找到当前节点是父亲节点的左子数时,修改当前节点的值即可。需要注意的是,当最大的值的节点访问完后,parent为空。所以,可以将end()的返回值设置成空。
 
参考代码如下
 
 下面将operator–实现一下。其实operator–和operator++的实现起来大不差不差,两个大情况正好和operator++的互为镜像。下面就直接提供一份代码以供参考。
 
而这里的简易迭代器其实是不符合set的要求的,因为set的key值是不能被修改的。所以我们需要封装一个const迭代器,而库里面set的普通迭代器和const迭代器都是const迭代器。
 
 这里顺便提一下map的普通 迭代器是如何支持修改Value而禁止修改Key的。map是通过模板T这个模板参数参数的pair<const K, Value>

 将上面的代码进行一下调整,将迭代器的模板参数增加两个,用于适配出const迭代器。然后修改一下set的迭代器部分的内容。
 
 接下来把map的部分写出来。
 
 map的普通迭代器要求Key不能被修改,Value可以修改。将pair里的K用const修饰,这样就避免Key在使用普通迭代器的情况下被修改了。
map的operator[]的模拟实现
在前面的map/set使用的文章中介绍map的[]时提到,其实map的operator[]底层使用了insert接口进行实现的。
 
 下面先将红黑树的insert接口进行一下修改。以符合我们的需求。
 
 然后修改set的insert接口的时候,问题出现了。
 
 这里由于set的iterator是const迭代器,insert返回的是普通迭代器。这里类型不匹配了。如何解决?先看一看库是怎么处理的。
 
 然后,直接借鉴库的写法将接口修改一下。
 
 根据库的写法修改后依旧还是有类型不匹配的问题。因为set的iterator是const迭代器,而insert的返回值是普通迭代器。要想能够匹配需要提供一个用普通迭代器构造const迭代器的接口。下面就看一看源码是如何实现的。
 
 库里面的解决方案是提供了一个特殊的构造函数。当iterator被实例化成普通迭代器时,这就是普通迭代器的拷贝构造。当iterator被实例化成const迭代器时,这个函数就会变成支持普通迭代器构造const迭代器的构造函数。这样上面set关于返回值的问题就能够得以解决了。
 
 解决了这个问题,那就将operator[]手撕出来map/set的封装的关键知识学习就差不多了。operator[]实现思路如下,通过复用insert[]来获取key所在的节点的pair。然后,取出pair的迭代器并使用operator->访问对应的Value即可。
 
总结
通过使用红黑树封装map/set,可以加深我们对于容器的理解。通过模拟实现set/map的关键部分,学习到了大佬在设计库的思想。一份红黑树模板可以实例化成两份不一样的容器。由于map和set性质上的差异,相应的红黑树的某些接口如,insert需要进行相应的调整。在迭代器部分设计的特殊的构造函数是非超巧妙的,让set的insert为了兼容map的insert的返回普通迭代器时,用这个普通迭代器构造成const迭代器,符合set的设计。
完整参考代码
//set
#pragma once
#include "RBTree.h"
namespace xyx
{
	template<class K>
	class set
	{	
		struct SetKeyOfT
		{
			const K& operator()(const K& key)
			{
				return key;
			}
		};
	public:
		typedef typename RBTree<K, K, SetKeyOfT>::const_iterator iterator;
		typedef typename RBTree<K, K, SetKeyOfT>::const_iterator const_iterator;
		const_iterator begin() const
		{
			return _tree.begin();
		}
		const_iterator end() const
		{
			return _tree.end();
		}
		pair<iterator, bool> insert(const K& key)
		{
			pair<typename RBTree<K, K, SetKeyOfT>::iterator, bool> p = _tree.Insert(key);
			return pair<iterator, bool>(p.first, p.second);
		}
	
	private:
		RBTree<K, K, SetKeyOfT> _tree;
	};
}
 
//map
#pragma once
#include "RBTree.h"
namespace xyx
{
	template<class K, class V>
	class map
	{	
		struct MapKeyOfT
		{
			const K& operator()(const pair<K, V>& kv)
			{
				return kv.first;
			}
		};
	public:
		typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::iterator iterator;
		typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::const_iterator const_iterator;
		iterator begin() 
		{
			return _tree.begin();
		}
		iterator end() 
		{
			return _tree.end();
		}
		const_iterator begin() const
		{
			return _tree.begin();
		}
		const_iterator end() const
		{
			return _tree.end();
		}
		V& operator[](const K& key)
		{
			pair<iterator, bool> p = insert(make_pair(key, V()));
			return p.first->second;
		}
		pair<iterator, bool> insert(const pair<K, V> kv)
		{
			return _tree.Insert(kv);
		}
	private:
		RBTree<K, pair<const K, V>, MapKeyOfT> _tree;
	};
}
 
//RBTree
#pragma once
#include <utility>
enum COLOR
{
	RED,
	BLACK
};
template<class T>
struct RBTreeNode
{
    RBTreeNode(const T& data)
        :_left(nullptr)
        ,_right(nullptr)
        ,_parent(nullptr)
        , _data(data)
        ,_color(RED)
    {}
	RBTreeNode<T>* _left;
	RBTreeNode<T>* _right;
	RBTreeNode<T>* _parent;
	T _data;
	COLOR _color;
};
template<class T, class Ptr, class Ref>
struct __TreeIterator
{
    typedef  RBTreeNode<T> Node;
    typedef __TreeIterator<T, T*, T&> iterator;
    typedef __TreeIterator<T, Ptr, Ref> Self;
    Node* _node;
    __TreeIterator(const iterator& it)
        :_node(it._node)
    {}
    __TreeIterator(Node* root)
        :_node(root)
    {}
    Ref operator*()
    {
        return _node->_data;
    }
    Ptr operator->()
    {
        return &_node->_data;
    }
    bool operator!=(const Self& s) const 
    {
        return _node != s._node;
    }
    bool operator==(const Self& s) const
    {
        return _node == s._node;
    }
    Self& operator--(int)
    {
        Self tmp = *this;
        //左子树不为空,访问左子树最右节点(最大节点)
        if (_node->_left)
        {
            Node* subRight = _node->_left;
            while (subRight->_right)
            {
                subRight = subRight->_right;
            }
            _node = subRight;
        }
        else //左子树为空,访问孩子是父亲右的祖先节点
        {
            Node* cur = _node;
            Node* parent = cur->_parent;
            while (parent && cur == parent->_right)
            {
                cur = parent;
                parent = parent->_parent;
            }
            _node = parent;
        }
        return tmp;
    }
    Self& operator--()
    {
        //左子树不为空,访问左子树最右节点(最大节点)
        if (_node->_left)
        {
            Node* subRight = _node->_left;
            while (subRight->_right)
            {
                subRight = subRight->_right;
            }
            _node = subRight;
        }
        else //左子树为空,访问孩子是父亲右的祖先节点
        {
            Node* cur = _node;
            Node* parent = cur->_parent;
            while (parent && cur == parent->_left)
            {
                cur = parent;
                parent = parent->_parent;
            }
            _node = parent;
        }
        return *this;
    }
    Self& operator++()
    {
        //右子树不为空,访问右子树最左节点(最小节点)
        if (_node->_right)
        {
            Node* subleft = _node->_right;
            while (subleft->_left)
            {
                subleft = subleft->_left;
            }
            _node = subleft;
        }
        else //右子树为空,访问孩子是父亲左的祖先节点
        {
            Node* cur = _node;
            Node* parent = cur->_parent;
            while (parent)
            {
                if (cur == parent->_left)
                {
                    break;
                }
                else
                {
                    cur = parent;
                    parent = parent->_parent;
                }
            }
            _node = parent;
        }
        return *this;
    }
};
template<class K, class T, class KeyOfT>
class RBTree
{
	typedef RBTreeNode<T> Node;
public:
    typedef __TreeIterator<T, T*, T&> iterator;
    typedef __TreeIterator<T, const T*, const T&> const_iterator;
    const_iterator begin() const
    {
        //树的最左节点(最小节点)
        Node* leftmin = _root;
        while (leftmin && leftmin->_left)
        {
            leftmin = leftmin->_left;
        }
        return const_iterator(leftmin);
    }
    const_iterator end() const
    {
        return const_iterator(nullptr);
    }
    iterator begin()
    {
        //树的最左节点(最小节点)
        Node* leftmin = _root;
        while (leftmin && leftmin->_left)
        {
            leftmin = leftmin->_left;
        }
        return iterator(leftmin);
    }
    iterator end()
    {
        return iterator(nullptr);
    }
    RBTree()
        :_root(nullptr) 
    {}
    Node* find(const K& key)
    {
        Node* parent = nullptr;
        Node* cur = _root;
        KeyOfT kot;
        while (cur)
        {
            if (kot(cur->data) < key)
            {
                parent = cur;
                cur = cur->_right;
            }
            else if (kot(cur->data) > key)
            {
                parent = cur;
                cur = cur->_left;
            }
            else
            {
                return cur;
            }
        }
        return nullptr;
    }
    pair <iterator, bool> Insert(const T& data)
    {
        //第一次插入数据
        if (_root == nullptr)
        {
            //根节点只能是黑色
            _root = new Node(data);
            _root->_color = BLACK;
            return make_pair(iterator(_root), true);
        }
        //找到合适的位置插入
        Node* parent = nullptr;
        Node* cur = _root;
        KeyOfT kot;
        while (cur)
        {
            if (kot(cur->_data) < kot(data))
            {
                parent = cur;
                cur = cur->_right;
            }
            else if (kot(cur->_data) > kot(data))
            {
                parent = cur;
                cur = cur->_left;
            }
            else
            {
                //key已经存在
                return make_pair(iterator(cur), false);
            }
        }
        //走到这里表示找到合适的位置插入
        cur = new Node(data);
        Node* newnode = cur;
        cur->_color = RED;//新节点为红色
        if (kot(parent->_data) < kot(data))
        {
            parent->_right = cur;
        }
        else
        {
            parent->_left = cur;
        }
        cur->_parent = parent;
        //红黑树的控制逻辑
        //父亲节点的颜色为黑色不需要调整
        //反之,需要调整
        while (parent && parent->_color == RED)
        {
            Node* grandFather = parent->_parent;
            if (parent == grandFather->_left)//考虑父亲在祖父的位置
            {
                Node* uncle = grandFather->_right;
                
                if (uncle && uncle->_color == RED)//uncle 存在且为红
                {
                    //将uncle和parent改成黑色,grandfather改成红色
                    uncle->_color = parent->_color = BLACK;
                    grandFather->_color = RED;
                    //如果祖父就是根节点,将祖父修改成黑色,退出即可
                    if (grandFather == _root)
                    {
                        grandFather->_color = BLACK;
                        break;
                    }
                    else //然后继续向上迭代处理
                    {
                        cur = grandFather;
                        parent = cur->_parent;
                    }
                }
                else //uncle不存在 或者 uncle存在且为黑
                {
                    if (parent->_left == cur) //单旋的场景
                    {
                        RotateR(grandFather);
                        parent->_color = BLACK;
                        grandFather->_color = RED;
                    }
                    else // LR双旋转
                    {
                        RotateL(parent);
                        RotateR(grandFather);
                        cur->_color = BLACK;
                        grandFather->_color = RED;
                    }
                    break; //旋转后直接退出即可
                }
            }
            else //parent == grandFather->_right
            {
                Node* uncle = grandFather->_left;
                if (uncle && uncle->_color == RED) //uncle 存在且为红
                {
                    uncle->_color = parent->_color = BLACK;
                    grandFather->_color = RED;
                    //如果祖父就是根节点,将祖父修改成黑色,退出即可
                    if (grandFather == _root)
                    {
                        grandFather->_color = BLACK;
                        break;
                    }
                    else //然后继续向上迭代处理
                    {
                        cur = grandFather;
                        parent = cur->_parent;
                    }
                }
                else //uncle不存在 或者 uncle存在且为黑
                {
                    if (parent->_right == cur) //单旋的场景
                    {
                        RotateL(grandFather);
                        parent->_color = BLACK;
                        grandFather->_color = RED;
                    }
                    else // RL双旋转
                    {
                        RotateR(parent);
                        RotateL(grandFather);
                        cur->_color = BLACK;
                        grandFather->_color = RED;
                    }
                    break; //旋转后直接退出即可
                }
            }
        }
        return make_pair(iterator(newnode), true);
    }
    void RotateL(Node* parent)
    {
        //_rotateCount++;
        //将curLeft连接到parent的右子树中
        //将parent连接到cur的左子树中
        //修改cur、parent、curLeft的_parent
        Node* cur = parent->_right;
        Node* curLeft = cur->_left;
        parent->_right = curLeft;
        // curLeft可能为空
        if (curLeft)
            curLeft->_parent = parent;
        cur->_left = parent;
        //提前保存parent的_parent避免节点丢失
        Node* ppnode = parent->_parent;
        parent->_parent = cur;
        //边界情况,修改_root
        if (parent == _root)
        {
            _root = cur;
            cur->_parent = nullptr;
        }
        else
        {
            if (ppnode->_left == parent)
                ppnode->_left = cur;
            else
                ppnode->_right = cur;
            cur->_parent = ppnode;
        }
    }
    void RotateR(Node* parent)
    {
        //++_rotateCount;
        //将cur的右子树连接到parent的左子数
        //让parent连接到cur的右子树
        //修改parent、cur、curRight的_parent
        Node* cur = parent->_left;
        Node* curRight = cur->_right;
        parent->_left = curRight;
        //curRight可能为空
        if (curRight)
            curRight->_parent = parent;
        //避免parent->_parent节点丢失
        Node* ppnode = parent->_parent;
        parent->_parent = cur;
        cur->_right = parent;
        //边界情况
        if (parent == _root)
        {
            _root = cur;
            cur->_parent = nullptr;
        }
        else
        {
            if (ppnode->_left == parent)
                ppnode->_left = cur;
            else
                ppnode->_right = cur;
            cur->_parent = ppnode;
        }
    }
    bool checkcolor(Node* root, int blacknum, int benchmark)
    {
        //处理边界情况
        if (root == nullptr) 
        {
            //走到NIL节点,基准值与当前路径黑节点数量不一致
            if (blacknum != benchmark)
                return false;
            return true;
        }
        
        //统计当前路径的黑节点数量
        if (root->_color == BLACK)
            ++blacknum;
        //出现连续红节点的情况
        if (root->_color == RED && root->_parent && root->_parent->_color == RED)
        {
            cout << root->_kv.first << "-> 位置出现连续红节点" << endl;
            return false;
        }
        //子问题分治
        return checkcolor(root->_left, blacknum, benchmark) && checkcolor(root->_right, blacknum, benchmark);
    }
    bool IsBalance()
    {
        return IsBalance(_root);
    }
    
    bool IsBalance(Node* root)
    {
        //处理边界情况
        if (root == nullptr)
            return true;
        
        //根节点只能为黑色
        if (_root->_color == RED)
        {
            return false;
        }
        //以最左路径的黑节点的数量为基准值
        int benchmark = 0;
        Node* cur = root;
        while (cur)
        {
            if(cur->_color == BLACK)
                ++benchmark;
            cur = cur->_left;
        }
        return checkcolor(root, 0, benchmark);
    }
    int Height()
    {
        return Height(_root);
    }
    int Height(Node* root)
    {
        //处理边界情况
        if (root == nullptr)
            return 0;
        int leftH = Height(root->_left);
        int rightH = Height(root->_right);
        return leftH > rightH ? leftH + 1 : rightH + 1;
    }
private:
	Node* _root;
//public:
//    int _rotateCount = 0;
};
                



![24-10-13-读书笔记(二十五)-《一只特立独行的猪》([中] 王小波)用一生来学习艺术](https://i-blog.csdnimg.cn/direct/a5338b8f0d424e91a58a5ca841b71b64.jpeg)











![HTB:Legacy[WriteUP]](https://i-blog.csdnimg.cn/direct/4410649ee0ac4c6381f34266b2f3d1b9.png)


