map和set模拟实现

本期我们来对map和set进行模拟实现,此处需要红黑树基础,没有看过红黑树的小伙伴建议先去看看红黑树,如果没了解过map和set的小伙伴也建议先去看一看,博客链接我都放在这里了

C++红黑树_KLZUQ的博客-CSDN博客

C++-map和set_KLZUQ的博客-CSDN博客 

目录

源码剖析

代码实现

迭代器

全部代码


源码剖析

我们先来看看源码

map和set模拟实现_第1张图片

这是set.h的头文件,其中stl_tree里实现的就是红黑树,里面还有set和multiset,我们先来看set

我们正常情况会认为,map和set的实现是两棵树,一棵树kv结构,一棵是k结构,但其实不是的,map和set使用的是一棵树

map和set模拟实现_第2张图片

这里的代码进行了一些裁减,当然裁减的是一些无关紧要的东西,我们来看重点

我们可以看到上面的rb_tree是一个kv结构

但是我们从typedef来看,无论是key还是value,他们其实都是Key,下面我们再看看map

map和set模拟实现_第3张图片

map也是kv结构,这里的key是Key,但是value是一个pair ,我们再看看树是怎么实现的

map和set模拟实现_第4张图片

我们可以看到,树的成员里有一个header,是link_type,而它的本质其实就是node* ,而树的节点存的是Value

但是这个value就是真的value吗?不是的,对于map而言,这里的value是pair,对于set而言,这里的value是Key,真正决定树里面存什么的是第二个模板参数传的是什么,我们继续看

map和set模拟实现_第5张图片

这里先是有一个基类base,里面就是红黑树的正常结构,color,parent,left和right

map和set模拟实现_第6张图片

然后用了一个子类去继承,这里才是node

map和set模拟实现_第7张图片

Value是value_field,rb_tree到底是k结构还是kv结构,谁也不知道,这里是搞了一个泛型

另外,这里的node也不是必须用继承,只是库里面喜欢这样写而已,一会我们实现时可以不用继承

我们可以体会到,库的设计是非常强的,只用了一棵红黑树就解决了所有问题,只取决于传的第二个模板参数,这里的value到底是key还是pair都可以由我们选择

另外这里可能会有人提出一个疑问,我们可以不传第一个模板参数Key吗?答案是不行的,因为map和set只是封装而已,核心部分的接口是调用树里面的,而树里面会调用find和erase等等,他们都是需要Key来适配的,我们再想想,map和set用的也并不是同一棵树,而是同一个类模板,同一个类模板用不同的模板参数实现出不同的类,大家要仔细想想

代码实现

map和set模拟实现_第8张图片

我们先把之前写的红黑树拿过来(红黑树源码可以去本期博客开头部分的链接里去找)

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

template
struct RBTree
{
	typedef RBTreeNode Node;
public:
	bool Insert(const T& data)

并且我们需要修改一下代码,这里我们把V改为了T,并且去掉了pair改为data

//MySet.h
#include"RBTree.h"
namespace bai
{
	template
	class set
	{
	private:
		RBTree_t;
	};
}
//MyMap.h
#include"RBTree.h"
namespace bai
{
	template
	class map
	{
	private:
		RBTree>_t;
	};
}

然后我们写一写框架

map和set模拟实现_第9张图片

此时的调用关系就是这样的 

下面我们还要继续修改红黑树里的代码,红黑树里有很多比较大小的语句,对于set没什么,但对于map,我们传的是pair,我们希望用first来比较,所以下面我们要进行多处修改,需要使用仿函数来进行控制

map和set模拟实现_第10张图片

这个仿函数在库里面也有,意思是把value里的key取出来

namespace bai
{
	template
	class set
	{
		struct SetKeyOfT
		{
			const K& operator()(const K& key)
			{
				return key;
			}
		};
	private:
		RBTree_t;
	};
}

对于set,我们返回key即可

namespace bai
{
	template
	class map
	{
		struct MapKeyOfT
		{
			const K& operator()(const pair& kv)
			{
				return kv.first;
			}
		};
	private:
		RBTree, MapKeyOfT>_t;
	};
}

对于map,我们取出pair的first返回

template
struct RBTree
{
	typedef RBTreeNode Node;
public:
	Node* Find(const K& key)
	{

	}
	bool Insert(const T& data)
	{
		if (_root == nullptr)
		{
			_root = new Node(data);
			_root->_col = BLACK;
			return true;
		}
		Node* cur = _root;
		Node* parent = nullptr;
		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
			{
				return false;
			}
		}
		cur = new Node(data);
        cur->_col = RED;
		if (kot(parent->_data) < kot(data))
		{
			parent->_right = cur;
		}
		else
		{
			parent->_left = cur;
		}
		cur->_parent = parent;

接着就是修改insert的部分代码,我们可以看到,比较大小时我们都使用的是kot,大家想想,如果不使用仿函数的话,我们该如何比较大小呢?对于set可以直接比较,但是map就不行了(其实这里map的pair也可以直接比较,库里面实现了,但是库里面的比较方法并不是我们需要的比较大小,所以这里需要我们自己写一下)

map和set模拟实现_第11张图片

我们简单画一下调用关系就是这样 ,这里的比较并不是使用kot比较,而是kot会把T对象的值拿来进行比较,比如map,就会把pair中的first返回

我们看到库里面除了kot,还有一个compare,这个compare是用来比较T的大小的,也就是说,库用了一个仿函数来取T对象里的值,又用另一个仿函数比较T的大小 

其实这个kot完全是为了map设计的,因为map的data比较不符合我们的需求,是一个pair,所以需要仿函数的帮助

大家仔细看,KeyOfT是在树这一层的,在map和set这一层是没有keyoft的

Node* Find(const K& key)
	{
		Node* cur = _root;
		KeyOfT kot;
		while (cur)
		{
			if (kot(cur->_data) < key)
			{
				cur = cur->_right;
			}
			else if(kot(cur->_data) > key)
			{
				cur = cur->_left;
			}
			else 
			{
				return cur;
			}
		}
		return nullptr;
	}

我们还要给红黑树写一个find

map和set模拟实现_第12张图片

map和set模拟实现_第13张图片

然后在set和map里再写一层insert,并且加上public 

map和set模拟实现_第14张图片

我们简单测试一下,没有问题

迭代器

接下来我们来实现迭代器

这是stl库里set的迭代器,是rep_type 

而它的本质就是rb_tree 

另外我们还发现,无论是迭代器还是const迭代器,它其实都是const_iterator

我们继续追溯源头,这是stl_tree.h里的,它的迭代器是这样的 

map和set模拟实现_第15张图片

这是它的定义,这里和节点那里一样,都是写了一个基类base,然后继承 

map和set模拟实现_第16张图片

这是base的结构 ,里面有一个节点的指针node

然后operator*返回里面的value_field,这个value_field对于set而言就是key,对于map而言就是pair,当然这些其实都不是重点

map和set模拟实现_第17张图片

 重点是++和--,我们实现列表等等++和--其实没啥,但是这里是一棵树,它++怎么到下一个节点呢?

map和set模拟实现_第18张图片

我们写代码一般是这样写的,begin是其实位置,而这棵树是二叉搜索树,所以应该是最左节点,也就是最小的值 ,我们看看库里面是不是也是这样的

map和set模拟实现_第19张图片

库里面返回的是一个leftmost

库里面返回的是一个header->left,和我们要实现的有一些不一样,一会我们会讲解一下库里面是什么情况,下面我们来看++怎么走

这里我们需要不借助栈来完成中序的非递归

map和set模拟实现_第20张图片

假设it在这个地方,++要找中序的下一个,也就是10,如果右树不为空,我们要访问右树的最左节点,对于所有节点,我们都可以这样做

map和set模拟实现_第21张图片

我们再看右为空的情况, 我们需要访问它的祖先(注意,这里不一定是父亲),如果it是父亲的左,那我们访问父亲,如果it是父亲的右(也就是it在7的位置时),说明it访问完后父亲也完了,我们需要去祖先里父亲是左的那一个,也就是8的位置

总结一下:右不为空,访问右树最左节点,右为空,访问孩子是父亲左的那个祖先

template
struct __TreeIterator
{
	typedef RBTreeNode Node;
	typedef __TreeIterator Self;
	Node* _node;
	__TreeIterator(Node* node)
		:_node(node)
	{}
	T& operator*()
	{
		return _node->_data;
	}
	T* operator->()
	{
		return &_node->_data;
	}
    bool operator!=(const Self& s)
	{
		return _node != s._node;
	}
	Self& operator++()
	{

	}
};

我们先把框架写好

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 && cur == parent->_right)
			{
				cur = cur->_parent;
				parent = parent->_parent;
			}
			_node = parent;
		}
		return *this;
	}

接着我们来实现++,if里边的逻辑很好理解,就是右树不为空,else里就是右树为空,需要找孩子是父亲左的那个祖先,最后返回*this即可,这里建议画图理解

map和set模拟实现_第22张图片

接着我们还要在树里面实现一下

map和set模拟实现_第23张图片 我们还要在set里写一下,但是此时是不能运行的,因为类模板没有被实例化时是没有生成具体代码的,里面可能有一些语法问题等等,编译器在这里是不敢去类模板里找这个iterator的,iterator是属于RBTree这个类域的,找出来还设计没有实例化的具体参数,比如这里的K,这个K具体是int还是char,是不知道的,所以编译器在这里是认不出来的,而且,编译器在类里面去取,取到的可能是一个内嵌类型(一种是typedef,一种是内部类),也可能是静态成员变量,那iterator到底是内嵌类型还是静态成员变量,编译器也不知道

map和set模拟实现_第24张图片

所以我们需要在这里加一个typename,告诉编译器等类模板实例化了再去找

map和set模拟实现_第25张图片

这时候我们的迭代器就能跑起来了,是不是很有趣?

map和set模拟实现_第26张图片

我们再把map的也补上

map和set模拟实现_第27张图片

和set不一样的是这里出错了 

map和set模拟实现_第28张图片

我们实现的operator*返回的是data,对于set而言data是key,但是对于map而言,是一个pair

pair是不支持流插入的

map和set模拟实现_第29张图片

所以这里我们可以使用->,另外大家还记得吗?这里是两个->,编译器优化了一个,这也是我们之前讲过的知识

map和set模拟实现_第30张图片

此时我们还可以使用auto和范围for

虽然上面我们实现了这么多,但是还是有很多大坑的

map和set模拟实现_第31张图片

比如我们的set是允许修改的,这可出现问题了,所以,任重道远啊

还记得我们上面说了库里面的无论iterator和const_iterator都是const吗?下面我们就要按照库的方法走

另外,map不能和set用一样的方法,对于map,key不允许修改,但是value是允许的

所以map的迭代器是正常的 

map和set模拟实现_第32张图片

也就是说,对于map来说,我们要不允许first,而允许second ,而且对于first这一行要在编译时就报错

map和set模拟实现_第33张图片

 库里面是这样做的,把key设为了const,下面我们来解决这些问题

map和set模拟实现_第34张图片

map和set模拟实现_第35张图片

我们给迭代器和树加上两个模板参数,如果是普通迭代器,我们传T*,T&,const就传const版本 

map和set模拟实现_第36张图片

再修改修改代码

        typedef typename RBTree::const_iterator iterator;
		typedef typename RBTree::const_iterator const_iterator;
		iterator begin()
		{
			return _t.begin();
		}
		iterator end()
		{
			return _t.end();
		}
		const_iterator begin() const
		{
			return _t.begin();
		}
		const_iterator end() const
		{
			return _t.end();
		}

接着我们在set里写出const版本,并且我们把const和普通迭代器都改为const,和库里面是一样的

我们再看看库里面的,const版本普通迭代器,和我们的还是有点不一样的

map和set模拟实现_第37张图片

此时我们运行,这里报错了 

这里的原因是

map和set模拟实现_第38张图片

t是一个普通对象

map和set模拟实现_第39张图片

就会调用普通的begin,返回一个普通迭代器,这里就存在一个转换

大家要知道,这两个迭代器是同一个类模板,传不同的参数, 实例化出不同的类型 

map和set模拟实现_第40张图片

首先我们要提供const版本的begin和end

 

我们再次看看库里面的,这是stl_set.h 里的

map和set模拟实现_第41张图片

我们和库里面改成一样的,把我们的const版本先屏蔽掉 ,结果成功了

map和set模拟实现_第42张图片

我们来看,如果我们不加const,t就是普通的t,只能调用普通的begin,返回的是普通的iterator,这里的iterator我们看起来是iterator,其实不是的

它是我们typedef出来的const_iterator 

map和set模拟实现_第43张图片

它的本质是这样的,也就是说我们只提供这个就行

那为什么我们还要写普通的iterator呢?

map和set模拟实现_第44张图片

因为我们使用的时候写的是普通的,这里set的问题就暂时解决了,下面我们来看map的

这里我们模仿库里面的写法,在k前加上const

map和set模拟实现_第45张图片

另外别忘了修改成员里的

map和set模拟实现_第46张图片

此时就可以只修改value,而key不能修改

map和set模拟实现_第47张图片

我们还要提供一下const版本的,普通的迭代器key不可以修改,value可以,const迭代器是都不可以修改

map和set模拟实现_第48张图片

比如这里,使用了const迭代器就都不可以修改了

map和set模拟实现_第49张图片

我们再把operator==实现一下,然后给这些能加const的加上const,下面我们实现一下operator--

--就是反过来,++走的是中序,--就是右子树,根,左子树的顺序

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 = cur->_parent;
				parent = parent->_parent;
			}
			_node = parent;
		}
		return *this;
	}

逻辑和++反一下即可,下面我们来看看库里面的结构

map和set模拟实现_第50张图片

 库和我们不同的是它增加了一个哨兵位的头节点,并且让它的左指向最左节点,右指向最右节点

这样的好处是可以快速找到最小节点和最大节点

map和set模拟实现_第51张图片

所以库里面的是leftmost和rightmost 

而它的end就直接是header,而我们的end是空,库里面的begin相对而言更高效一点,不够这是要付出代价的,比如在最左边插入一个节点,header的left就需要修改,另外,这里的header的parent是指向根的,然后root的parent指向header,删除,旋转等等都是需要维护header的

map和set模拟实现_第52张图片

而且还要单独判断一下这个特殊情况,不然会死循环,这里cur等于parent的右,就会无限循环

map和set模拟实现_第53张图片

map和set模拟实现_第54张图片

我们看库里面的,这些我们了解即可

下面我们再实现一下operator[ ]

map和set模拟实现_第55张图片

 operator[ ] 的实现需要insert,我们看看库里面的insert,first是迭代器,second是bool

map和set模拟实现_第56张图片

所以我们需要把树里面的insert改一下

map和set模拟实现_第57张图片 map和set模拟实现_第58张图片

修改返回值和返回类型

map和set模拟实现_第59张图片 

map和set模拟实现_第60张图片

接着修改map和set的insert

map和set模拟实现_第61张图片

然后我们编译,就出错了 ,set的insert是编不过的

这里的t是普通对象,调用insert,返回普通迭代器,也就是pair里的迭代器是普通迭代器

但是这里的迭代器是const_iterator

map和set模拟实现_第62张图片

是这个样子,我们来看看库里面是怎么解决的

这是stl_set库,它用了pair的first去构造了一个

 map和set模拟实现_第63张图片

 结合起来看一下

map和set模拟实现_第64张图片

再看我们的,大家先想想,这里选中的iterator是const还是普通的 ?
是const,而后面的ret.first是普通迭代器,这里是不能用make_pair的一个原因,make_pair是自己推

这里的本质是调用了pair的构造函数

map和set模拟实现_第65张图片

是这样子的,所以这里的本质是用普通迭代器构造const迭代器,我们以前实现的迭代器都是不支持的

map和set模拟实现_第66张图片

库里面支持这样玩的原因是因为有这样一个函数 ,我们看最后一行,按理来说迭代器是不需要写拷贝构造的,但是这里并不是纯的拷贝构造,这里没有用self,大家仔细看self和iterator的区别

self就是这个迭代器,但iterator并不一定是

再结合这里来看

 当这个类被实例化成const迭代器时,这个函数是一个构造函数,支持普通迭代器构造const迭代器

 

普通迭代器不受传的Ptr和Ref影响, const迭代器传const Ref和const Ptr时,普通迭代器还是value&和value*,始终是一个普通迭代器,这个函数就相当于一个普通的构造函数,它的参数是普通迭代器,用来构造const迭代器(链表那里也是这样做的)

当这个类被实例化为普通迭代器时,这个函数就是一个拷贝构造,普通迭代器构造普通迭代器,就是一个拷贝构造

map和set模拟实现_第67张图片

所以我们也需要加上构造

 我们上面那么费时费力的原因就是因为这个东西,大家要想清楚

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

此时我们终于可以完成operator[ ] 了,这里先调insert,然后调用make_pair,first是key,value是V的缺省值,如果没有,会先插入,如果有了就不插入,ret是pair,pair.first是一个迭代器,然后用->取second

map和set模拟实现_第68张图片

我们简单测试一下,就和库里面差不多了

全部代码

//RBTree.h
#include
using namespace std;

enum Colour
{
	RED,
	BLACK
};
template
struct RBTreeNode
{
	RBTreeNode* _left;
	RBTreeNode* _right;
	RBTreeNode* _parent;
	T _data;
	Colour _col;
	RBTreeNode(const T& data)
		:_left(nullptr)
		, _right(nullptr)
		, _parent(nullptr)
		, _data(data)
		,_col(RED)
	{}
};

template
struct __TreeIterator
{
	typedef RBTreeNode Node;
	typedef __TreeIterator Self;
	typedef __TreeIterator Iterator;
	__TreeIterator(const Iterator& it)
		:_node(it._node)
	{}
	Node* _node;
	__TreeIterator(Node* node)
		:_node(node)
	{}
	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--()
	{
		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 = 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 && cur == parent->_right)
			{
				cur = cur->_parent;
				parent = parent->_parent;
			}
			_node = parent;
		}
		return *this;
	}
};

template
struct RBTree
{
	typedef RBTreeNode Node;
public:
	typedef __TreeIterator iterator;
	typedef __TreeIterator const_iterator;
	iterator begin()
	{
		Node* leftMin = _root;
		while (leftMin && leftMin->_left)//前面加条件是防止空树
		{
			leftMin = leftMin->_left;
		}
		return iterator(leftMin);
	}
	iterator end()
	{
		return iterator(nullptr);
	}
	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);
	}
	Node* Find(const K& key)
	{
		Node* cur = _root;
		KeyOfT kot;
		while (cur)
		{
			if (kot(cur->_data) < key)
			{
				cur = cur->_right;
			}
			else if(kot(cur->_data) > key)
			{
				cur = cur->_left;
			}
			else 
			{
				return cur;
			}
		}
		return nullptr;
	}
	pair Insert(const T& data)
	{
		if (_root == nullptr)
		{
			_root = new Node(data);
			_root->_col = BLACK;
			return make_pair(iterator(_root),true);
		}
		Node* cur = _root;
		Node* parent = nullptr;
		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
			{
				return make_pair(iterator(cur), false);
			}
		}
		cur = new Node(data);
		cur->_col = RED;
		Node* newnode = cur;
		if (kot(parent->_data) < kot(data))
		{
			parent->_right = cur;
		}
		else
		{
			parent->_left = cur;
		}
		cur->_parent = parent;
		
		while (parent && parent->_col == RED)
		{
			Node* grandfather = parent->_parent;
			if (parent == grandfather->_left)//parent在grandfather的左边
			{
				Node* uncle = grandfather->_right;
				if (uncle && uncle->_col == RED)//叔叔存在且为红
				{
					//变色
					uncle->_col = BLACK;
					parent->_col = BLACK;
					grandfather->_col = RED;
					//继续向上处理
					cur = grandfather;
					parent = cur->_parent;
				}
				else//叔叔不存在/存在且为黑
				{
					if (cur == parent->_left)
					{
						RotateR(grandfather);
						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					else
					{
						RotateL(parent);
						RotateR(grandfather);
						cur->_col = BLACK;
						grandfather->_col = RED;
					}
					break;
				}
			}
			else//parent在grandfather的右边
			{
				Node* uncle = grandfather->_left;
				if (uncle && uncle->_col == RED)//叔叔存在且为红
				{
					uncle->_col = BLACK;
					parent->_col = BLACK;
					grandfather->_col = RED;
					cur = grandfather;
					parent = cur->_parent;
				}
				else//叔叔不存在/存在且为黑
				{
					if (cur == parent->_right)
					{
						RotateL(grandfather);
						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					else
					{
						RotateR(parent);
						RotateL(grandfather);
						cur->_col = BLACK;
						grandfather->_col = RED;
					}
					break;
				}
			}
		}
		_root->_col = BLACK;
		return make_pair(iterator(newnode), true);
	}

	void RotateL(Node* parent)//左单旋
	{
		Node* cur = parent->_right;
		Node* curleft = cur->_left;
		parent->_right = curleft;
		if (curleft)
		{
			curleft->_parent = parent;
		}
		cur->_left = parent;
		Node* ppnode = parent->_parent;
		parent->_parent = cur;
		if (parent == _root)//parent是根节点
		{
			_root = cur;
			cur->_parent = nullptr;
		}
		else
		{
			if (ppnode->_left == parent)
			{
				ppnode->_left = cur;
			}
			else
			{
				ppnode->_right = cur;
			}
			cur->_parent = ppnode;
		}
	}

	void RotateR(Node* parent)//右单旋
	{
		Node* cur = parent->_left;
		Node* curright = cur->_right;
		parent->_left = curright;
		if (curright)
		{
			curright->_parent = parent;
		}
		Node* ppnode = parent->_parent;
		cur->_right = parent;
		parent->_parent = cur;
		if (ppnode == nullptr)
		{
			_root = cur;
			cur->_parent = nullptr;
		}
		else
		{
			if (ppnode->_left == parent)
			{
				ppnode->_left = cur;
			}
			else
			{
				ppnode->_right = cur;
			}
			cur->_parent = ppnode;
		}
	}
	bool IsBalance()
	{
		return IsBalance(_root);
	}
	bool CheckColour(Node* root,int blacknum,int benchmark)//检查节点颜色
	{
		if (root == nullptr)
		{
			if (benchmark != blacknum)//黑色节点数量不对
				return false;
			return true;
		}
		if (root->_col == BLACK)//检测黑色节点数量
		{
			++blacknum;
		}
		if (root->_col == RED && root->_parent && root->_parent->_col == RED)
		{
			cout << root->_kv.first << "连续红节点" << endl;
			return false;
		}

		return CheckColour(root->_left,blacknum, benchmark)
			&& CheckColour(root->_right, blacknum, benchmark);

	}
	bool IsBalance(Node* root)
	{
		if (root == nullptr)
			return true;
		if (root->_col != BLACK)
			return false;
		int benchmark = 0;//黑色节点基准值
		Node* cur = _root;
		while (cur)
		{
			if (cur->_col==BLACK)
				++benchmark;
			cur = cur->_left;
		}
		return CheckColour(root,0, benchmark);
	}
private:
	Node* _root = nullptr;
};
//MySet.h
#include"RBTree.h"
namespace bai
{
	template
	class set
	{
		struct SetKeyOfT
		{
			const K& operator()(const K& key)
			{
				return key;
			}
		};
	public:
		typedef typename RBTree::const_iterator iterator;
		typedef typename RBTree::const_iterator const_iterator;
		const_iterator begin() const
		{
			return _t.begin();
		}
		const_iterator end() const
		{
			return _t.end();
		}
		/*const_iterator begin() const
		{
			return _t.begin();
		}
		const_iterator end() const
		{
			return _t.end();
		}*/
		pair insert(const K& key)
		{
			pair::iterator, bool> ret = _t.Insert(key);
			return pair(ret.first,ret.second);
		}
	private:
		RBTree_t;
	};
}
//MyMap.h
#include"RBTree.h"
namespace bai
{
	template
	class map
	{
		struct MapKeyOfT
		{
			const K& operator()(const pair& kv)
			{
				return kv.first;
			}
		};
	public:
		typedef typename RBTree, MapKeyOfT>::iterator iterator;
		typedef typename RBTree, MapKeyOfT>::const_iterator const_iterator;
		iterator begin()
		{
			return _t.begin();
		}
		iterator end()
		{
			return _t.end();
		}
		const_iterator begin() const
		{
			return _t.begin();
		}
		const_iterator end() const
		{
			return _t.end();
		}
		V& operator[](const K& key)
		{
			pair ret = insert(make_pair(key, V()));
			return ret.first->second;
		}
		pair insert(const pair& kv)
		{
			return _t.Insert(kv);
		}
	private:
		RBTree, MapKeyOfT>_t;
	};
}

以上即为本期全部内容,希望大家可以有所收获

如有错误,还请指正

你可能感兴趣的:(开发语言,c++,数据结构,map,set)