【C++】23:封装set和map

目录

一、源码和框架分析

二、创建项目结构

三、模拟实现set和map

四、测试set中insert的实现

五、迭代器Iterator的实现

[5.1 迭代器类的结构设计](#5.1 迭代器类的结构设计)

[5.2 RBTree中封装迭代器](#5.2 RBTree中封装迭代器)

[5.3 set中封装迭代器](#5.3 set中封装迭代器)

[5.4 operator++的实现](#5.4 operator++的实现)

[5.5 set测试代码](#5.5 set测试代码)

[5.6 map中封装迭代器](#5.6 map中封装迭代器)

[5.7 map测试代码](#5.7 map测试代码)

[5.8 Key修改的问题](#5.8 Key修改的问题)

[5.9 operator--的实现](#5.9 operator--的实现)

[5.10 逆序遍历set的问题](#5.10 逆序遍历set的问题)

六、operator[]的实现

[6.1 RBTree树insert修改](#6.1 RBTree树insert修改)

[6.2 mymap中修改insert和operator[]](#6.2 mymap中修改insert和operator[])

七、代码

[7.1 RBtree.h](#7.1 RBtree.h)

[7.2 mymap.h](#7.2 mymap.h)

[7.3 myset.h](#7.3 myset.h)

[7.4 test.cpp](#7.4 test.cpp)


一、源码和框架分析

我们学习红黑树的模拟实现之后,我们可以模拟实现set和map。可是set是Key结构的红黑树,Map是Key/Value结构的红黑树,我们要实现两颗红黑树嘛?我们来看一下库里面是如何实现的,如下所示:

  • 通过上图对框架的分析,我们可以看到源码中rb_tree用了一个巧妙的泛型思想实现,rb_tree是实现key的搜索场景,还是key/value的搜索场景不是直接写死的,而是由第二个模板参数Value决定_rb_tree_node中存储的数据类型。
  • set实例化rb_tree时第二个模板参数给的是key,map实例化rb_tree时第二个模板参数给的是pair<const key,T>,这样一颗红黑树既可以实现key搜索场景的set,也可以实现key/value搜索场景的map。
  • 要注意一下,源码里面模板参数是用T代表value,而内部写的value_type不是我们我们日常key/value场景中说的value,源码中的value_type反而是红黑树结点中存储的真实的数据的类型。
  • rb_tree第二个模板参数Value已经控制了红黑树结点中存储的数据类型,为什么还要传第一个模板参数Key呢?尤其是set,两个模板参数是一样的,这是很多同学这时的一个疑问。要注意的是对于map和set,find/erase时的函数参数都是Key,所以第一个模板参数是传给find/erase等函数做形参的类型的。对于set而言两个参数是一样的,但是对于map而言就完全不一样了,mapinsert的是pair对象,但是find和ease的是Key对象。

二、创建项目结构

红黑树的模拟实现

我们将红黑树的模拟实现的代码拷贝进我们的项目里面,然后再创建两个头文件,分别是myset和mymap,将set和map的实现放到命名空间zx里面,用来区别库里面的set和map。

如下所示:

RBTree的代码:不需要大小,高度,中序遍历等代码,所有将这些注释掉。

cpp 复制代码
#pragma once
#include<iostream>
using namespace std;

enum color
{
	RED,
	BLACK
};
template<class K, class V>
struct RBTreeNode
{
	pair<K, V> _kv;
	RBTreeNode<K, V>* _parent;
	RBTreeNode<K, V>* _left;
	RBTreeNode<K, V>* _right;
	color _col;

	RBTreeNode(const pair<K, V>& kv)
		:_kv(kv)
		, _parent(nullptr)
		, _left(nullptr)
		, _right(nullptr)
	{
	}
};
template<class K, class V>
class RBTree
{
	typedef RBTreeNode<K, V> Node;
public:
	void RotateR(Node* parent)
	{
		Node* pParent = parent->_parent;

		Node* subL = parent->_left;
		Node* subLR = subL->_right;

		parent->_left = subLR;
		if (subLR != nullptr)
			subLR->_parent = parent;

		subL->_right = parent;
		parent->_parent = subL;

		if (parent == _root)
		{
			_root = subL;
			subL->_parent = nullptr;
		}
		else
		{
			if (pParent->_left == parent)
			{
				pParent->_left = subL;
			}
			else
			{
				pParent->_right = subL;
			}
			subL->_parent = pParent;
		}
	}
	void RotateL(Node* parent)
	{
		Node* pParent = parent->_parent;
		Node* subR = parent->_right;
		Node* subRL = subR->_left;

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

		subR->_left = parent;
		parent->_parent = subR;

		if (parent == _root)
		{
			_root = subR;
			subR->_parent = nullptr;
		}
		else
		{
			if (pParent->_left == parent)
			{
				pParent->_left = subR;
			}
			else
			{
				pParent->_right = subR;
			}
			subR->_parent = pParent;
		}
	}
	bool Insert(const pair<K, V>& kv)
	{
		if (_root == nullptr)
		{
			_root = new Node(kv);
			_root->_col = BLACK;
			return true;
		}
		Node* parent = nullptr;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_kv.first < kv.first)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (cur->_kv.first > kv.first)
			{
				parent = cur;
				cur = cur->_left;
			}
			else {
				return false;
			}
		}
		cur = new Node(kv);
		cur->_col = RED;
		if (parent->_kv.first < kv.first)
		{
			parent->_right = cur;
		}
		else
		{
			parent->_left = cur;
		}
		cur->_parent = parent;
		//父亲是红色,出现连续的红色节点,需要处理
		while (parent && parent->_col == RED)
		{
			Node* grandfather = parent->_parent;
			if (grandfather->_left == parent)
			{
				//   g
				// p  u
				Node* uncle = grandfather->_right;
				if (uncle && uncle->_col == RED)  //叔叔存在,并且叔叔的颜色为红色
				{
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;
					//继续往上处理
					cur = grandfather;
					parent = cur->_parent;
				}
				else   //叔叔不存在或者叔叔的颜色为黑色
				{
					if (cur == parent->_left)
					{
						//    g
						//  p  u
						//c
						RotateR(grandfather);
						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					else
					{
						//    g
						//  p    u
						//	 c
						RotateL(parent);
						RotateR(grandfather);
						cur->_col = BLACK;
						grandfather->_col = RED;
					}
					break;
				}
			}
			else
			{
				//   g
				// u   p
				Node* uncle = grandfather->_left;
				// 叔叔存在切为红,变色即可
				if (uncle && uncle->_col == RED)
				{
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;

					cur = grandfather;
					parent = cur->_parent;
				}
				else
				{
					//    g
					// u     p
					//         c
					if (cur == parent->_right)
					{
						RotateL(grandfather);
						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					else
					{
						//     g
						//   u    p
						//       c
						RotateR(parent);
						RotateL(grandfather);
						cur->_col = BLACK;
						grandfather->_col = RED;
					}
					break;
				}
			}
		}

		_root->_col = BLACK;
		return true;
	}
	//void InOrder()
	//{
	//	_InOrder(_root);
	//}
	//int Height()
	//{
	//	return _Height(_root);
	//}
	//int Size()
	//{
	//	return _Size(_root);
	//}
	//bool IsBalance()
	//{
	//	if (_root == nullptr)
	//		return true;
	//	if (_root->_col == RED)
	//		return false;
	//	// 参考值
	//	int refNum = 0;
	//	Node* cur = _root;
	//	while (cur)
	//	{
	//		if (cur->_col == BLACK)
	//		{
	//			++refNum;
	//		}
	//		cur = cur->_left;
	//	}
	//	return Check(_root, 0, refNum);
	//}
private:
	Node* _root = nullptr;

	//void _InOrder(Node* root)
	//{
	//	if (root == nullptr)
	//	{
	//		return;
	//	}
	//	_InOrder(root->_left);
	//	cout << root->_kv.first << "::" << root->_kv.second << endl;
	//	_InOrder(root->_right);
	//}
	//int _Height(Node* root)
	//{
	//	if (root == 0)
	//		return 0;
	//	int leftHeight = _Height(root->_left);
	//	int rightHeight = _Height(root->_right);
	//	return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
	//}
	//int _Size(Node* root)
	//{
	//	if (root == 0)
	//		return 0;
	//	return _Size(root->_left) + _Size(root->_right) + 1;
	//}
	//bool Check(Node* root, int blackNum, const int refNum)
	//{
	//	if (root == nullptr)
	//	{
	//		// 前序遍历走到空时,意味着一条路径走完了
	//		//cout << blackNum << endl;
	//		if (refNum != blackNum)
	//		{
	//			cout << "存在黑色结点的数量不相等的路径" << endl;
	//			return false;
	//		}
	//		return true;
	//	}
	//	// 检查孩子不太方便,因为孩子有两个,且不一定存在,反过来检查父亲就方便多了
	//	if (root->_col == RED && root->_parent->_col == RED)
	//	{
	//		cout << root->_kv.first << "存在连续的红色结点" << endl;
	//		return false;
	//	}
	//	if (root->_col == BLACK)
	//	{
	//		blackNum++;
	//	}
	//	return Check(root->_left, blackNum, refNum)
	//		&& Check(root->_right, blackNum, refNum);
	//}
};

三、模拟实现set和map

  1. 我们这里相比源码调整一下,key参数就用K,value参数就用V,红黑树中的数据类型,我们使用T。我们再set和map中创建一个红黑树类型的变量,如下所示:
  2. 再set里面,我们传入两个K类型的变量给RBTree,在map里面,我们传入K和pair类型的变量给RBTree。因为我们传入的类型不同,所以就需要修改红黑树的代码,如下所示:
  3. 现在又有新的问题了,那现在我们如何来比较Key呢?在RBTree实现了泛型。不知道T参数导致是K,还是pair<K,V>,那么insert内部进行插入逻辑比较时,就没办法进行比较,因为pair的默认支持的是key和value一起参与比较,我们需要时的任何时候只比较key,那现在怎么办呢?虽然在RBTree这一层我们不知道是K还是pair<K,V>,但是在myset和mymap这一层我们是知道是K还是pair<K,V>的。所以我们在map和set层分别实现一个MapKeyOfT和SetKeyOfT的仿函数传给RBTree的KeyOfT,然后RBTree中通过KeyOfT仿函数取出T类型对象中的key,再进行比较,如下所示:

四、测试set中insert的实现

set代码如下所示:

cpp 复制代码
#pragma once
#include"RBTree.h"

namespace zx
{
	template<class K>
	class set
	{
		struct SetKeyOfT
		{
			const K& operator()(const K& key)
			{
				return key;
			}
		};
	public:
		bool insert(const K& key)
		{
			return _t.Insert(key);
		}
	private:
		RBTree<K, K, SetKeyOfT> _t;
	};
}

测试代码如下所示:

cpp 复制代码
#include"myset.h"
#include"mymap.h"
#include"RBTree.h"

void testset()
{
	zx::set<int> s;
	s.insert(5);
	s.insert(1);
	s.insert(3);
	s.insert(2);
	s.insert(6);
}
int main()
{
	testset();
	return 0;
}

运行代码之后程序没有崩溃,就说明没有问题。

五、迭代器Iterator的实现

iterator实现的大框架跟list的iterator思路是一致的,用一个类型封装结点的指针,再通过重载运算符实现,迭代器像指针一样访问的行为。

5.1 迭代器类的结构设计

代码如下所示:

cpp 复制代码
template<class T,class Ref,class Ptr>
struct RBTreeIterator
{
	typedef RBTreeNode<T> Node;
	typedef RBTreeIterator<T, Ref, Ptr> Self;
	Node* _node;
	RBTreeIterator(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;
	}
};

5.2 RBTree中封装迭代器

cpp 复制代码
typedef RBTreeIterator<T, T&, T*> Iterator;
typedef RBTreeIterator<T, const T&, const T*> ConstIterator;
Iterator Begin()
{
	Node* cur = _root;
	while (cur&&cur->_left)
	{
		cur = cur->_left;
	}
	return Iterator(cur);
}
Iterator End()
{
	return nullptr;
}
ConstIterator Begin() const
{
	Node* cur = _root;
	while (cur && cur->_left)
	{
		cur = cur->_left;
	}
	return Iterator(cur);
}
ConstIterator End() const
{
	return nullptr;
}

5.3 set中封装迭代器

cpp 复制代码
typedef typename RBTree<K, K, SetKeyOfT>::Iterator iterator;
typedef typename RBTree<K, K, SetKeyOfT>::ConstIterator 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();
}

5.4 operator++的实现

  1. 这里的难点是operator++和operator--的实现。之前使用部分,我们分析了,map和set的迭代器走的是中序遍历,左子树->根结点->右子树,那么begin()会返回中序第一个结点的迭代器。
  2. 迭代器++的核心逻辑就是不看全局,只看局部,只考虑当前中序局部要访问的下一个结点。
  3. 迭代器++时,如果it指向的结点的右子树不为空,代表当前结点已经访问完了,要访问下一个结点是右子树的中序第一个,一棵树中序第一个是最左结点,所以直接找右子树的最左结点即可。
  4. 迭代器++时,如果it指向的结点的右子树空,代表当前结点已经访问完了且当前结点所在的子树也访问完了,要访问的下一个结点在当前结点的祖先里面,所以要沿着当前结点到根的祖先路径向上找。

代码如下所示:

cpp 复制代码
Self operator++()
{
	if (_node->_right) 
	{
		//右不为空,下一个访问的结点是右子树的最左结点
		Node* min = _node->_right;
		while (min->_left)
		{
			min = min->_left;
		}
		_node = min;
	}
	else
	{
		//右为空,下一个是祖先里面孩子是父亲左的那个祖先
		Node* cur = _node;
		Node* parent = cur->_parent;
		while (parent && parent->_right == cur)
		{
			cur=parent;
			parent = parent->_parent;
		}
		_node = parent;
	}
	return *this;
}

5.5 set测试代码

cpp 复制代码
#include"myset.h"
#include"mymap.h"
#include"RBTree.h"

void testset()
{
	zx::set<int> s;
	s.insert(5);
	s.insert(1);
	s.insert(3);
	s.insert(2);
	s.insert(6);
	zx::set<int>::iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
}
int main()
{
	testset();
	return 0;
}

运行结果:

5.6 map中封装迭代器

cpp 复制代码
typedef typename  RBTree<K, pair<K, V>, MapKeyOfT>::Iterator iterator;
typedef typename  RBTree<K, pair<K, V>, MapKeyOfT>::ConstIterator 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();
}
bool insert(const pair<K,V>& kv)
{
	return _t.Insert(kv);
}

5.7 map测试代码

cpp 复制代码
#include<string>
#include"myset.h"
#include"mymap.h"
#include"RBTree.h"

void testset()
{
	zx::set<int> s;
	s.insert(5);
	s.insert(1);
	s.insert(3);
	s.insert(2);
	s.insert(6);
	zx::set<int>::iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
}
void testmap()
{
	zx::map<string, string> dict;
	dict.insert({ "left","左边" });
	dict.insert({ "right","右边" });
	dict.insert({ "sort","排序" });
	dict.insert({ "auto","自动" });
	zx::map<string, string>::iterator it = dict.begin();
	while (it != dict.end())
	{
		cout << it->first << "::" << it->second << endl;
		++it;
	}
	cout << endl;
}
int main()
{
	//testset();
	testmap();
	return 0;
}

运行结果如下:

5.8 Key修改的问题

如下所示,我们所模拟实现的代码中,Key是可以修改的,但是库里面的中的Key是不支持修改的。

cpp 复制代码
#include<string>
#include"myset.h"
#include"mymap.h"
#include"RBTree.h"

void testset()
{
	zx::set<int> s;
	s.insert(5);
	s.insert(1);
	s.insert(3);
	s.insert(2);
	s.insert(6);
	zx::set<int>::iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
}
void testmap()
{
	zx::map<string, string> dict;
	dict.insert({ "left","左边" });
	dict.insert({ "right","右边" });
	dict.insert({ "sort","排序" });
	dict.insert({ "auto","自动" });
	zx::map<string, string>::iterator it = dict.begin();
	while (it != dict.end())
	{
		it->first += 'x';
		it->second += 'x';
		cout << it->first << "::" << it->second << endl;
		++it;
	}
	cout << endl;
}
int main()
{
	//testset();
	testmap();
	return 0;
}

运行结果如下:

我们发现Key的值被修改了。按理来说Key不能修改的。

我们可以将K设置成const,pair里面的K也设置成const,如下所示:

5.9 operator--的实现

迭代器-的实现跟++的思路完全类似,逻辑正好反过来即可,因为他访问顺序是右子树->根结点->左子树,代码如下所示:

cpp 复制代码
Self operator--()
{
	if (_node->_left)
	{
		//左子树不为空,下一个是中序左子树的最后一个
		Node* rightMost = _node->_left;
		while (rightMost->_right)
		{
			rightMost = rightMost->_right;
		}
		_node = rightMost;
	}
	else
	{
		//左子树为空,下一个结点是父亲右的那个祖先
		Node* cur = _node;
		Node* parent = cur->_parent;
		while (parent && cur == parent->_left)
		{
			cur = parent;
			parent = cur->_parent;
		}
		_node = parent;
	}
	return *this;
}

5.10 逆序遍历set的问题

我们使用end()迭代器,然后--迭代器来遍历set。

代码如下所示:

cpp 复制代码
#include<string>
#include"myset.h"
#include"mymap.h"
#include"RBTree.h"

void testset1()
{
	zx::set<int> s;
	s.insert(5);
	s.insert(1);
	s.insert(3);
	s.insert(2);
	s.insert(6);
	zx::set<int>::iterator it = s.end();
	while (it != s.begin())
	{
		--it;
		cout << *it << " ";
	}
	cout << endl;
}
int main()
{
	testset1();
	return 0;
}

我们运行之后,发现程序崩溃了,这是为什么呢?

这是因为我们使用nullptr来充当end()迭代器,对空指针--会发生错误,所以我们需要特殊处理。如果迭代器里面的_node是nullptr的话,就需要找到set中的最右结点,但是我们iterator类中只有一个nullptr,如何才能找到最右结点呢?我们可以在iterator类里面再增加一个成员变量root,把红黑树的根结点传入进来,就可以找到最右结点了。代码如下所示:

cpp 复制代码
Self operator--()
{
	if (_node == nullptr)
	{
		Node* right = _root;
		while (right && right->_right)
		{
			right = right->_right;
		}
		_node = right;
	}
	else if (_node->_left)
	{
		//左子树不为空,下一个是中序左子树的最后一个
		Node* rightMost = _node->_left;
		while (rightMost->_right)
		{
			rightMost = rightMost->_right;
		}
		_node = rightMost;
	}
	else
	{
		//左子树为空,下一个结点是父亲右的那个祖先
		Node* cur = _node;
		Node* parent = cur->_parent;
		while (parent && cur == parent->_left)
		{
			cur = parent;
			parent = cur->_parent;
		}
		_node = parent;
	}
	return *this;
}

六、operator[]的实现

  • map要支持[]主要需要修改insert返回值支持,修改RBtree中的insert返回值为pair<Iterator,bool>Insert(const T& data)
  • 有了insert支持[]实现就很简单了,代码如下所示:

6.1 RBTree树insert修改

cpp 复制代码
pair<Iterator,bool> Insert(const T& data)
{
	if (_root == nullptr)
	{
		_root = new Node(data);
		_root->_col = BLACK;
		return pair<Iterator, bool>( iterator(_root,_root),true );
		//return {iterator(_root,_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 {
			return { iterator(cur,_root),false };
		}
	}
	cur = new Node(data);
	Node* newnode = cur;//变色旋转之后可能会更新cur
	cur->_col = RED;
	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 (grandfather->_left == parent)
		{
			//   g
			// p  u
			Node* uncle = grandfather->_right;
			if (uncle && uncle->_col == RED)  //叔叔存在,并且叔叔的颜色为红色
			{
				parent->_col = uncle->_col = BLACK;
				grandfather->_col = RED;
				//继续往上处理
				cur = grandfather;
				parent = cur->_parent;
			}
			else   //叔叔不存在或者叔叔的颜色为黑色
			{
				if (cur == parent->_left)
				{
					//    g
					//  p  u
					//c
					RotateR(grandfather);
					parent->_col = BLACK;
					grandfather->_col = RED;
				}
				else
				{
					//    g
					//  p    u
					//	 c
					RotateL(parent);
					RotateR(grandfather);
					cur->_col = BLACK;
					grandfather->_col = RED;
				}
				break;
			}
		}
		else
		{
			//   g
			// u   p
			Node* uncle = grandfather->_left;
			// 叔叔存在切为红,变色即可
			if (uncle && uncle->_col == RED)
			{
				parent->_col = uncle->_col = BLACK;
				grandfather->_col = RED;

				cur = grandfather;
				parent = cur->_parent;
			}
			else
			{
				//    g
				// u     p
				//         c
				if (cur == parent->_right)
				{
					RotateL(grandfather);
					parent->_col = BLACK;
					grandfather->_col = RED;
				}
				else
				{
					//     g
					//   u    p
					//       c
					RotateR(parent);
					RotateL(grandfather);
					cur->_col = BLACK;
					grandfather->_col = RED;
				}
				break;
			}
		}
	}

	_root->_col = BLACK;
	return { iterator(newnode,_root),true };
}

6.2 mymap中修改insert和operator[]

cpp 复制代码
pair<iterator,bool> insert(const pair<K, V>& kv)
{
	return _t.Insert(kv);
}
V& operator[](const K& key)
{
	pair<iterator, bool> ret = insert({ key,V() });
	return ret.first->second;
}

七、代码

7.1 RBtree.h

cpp 复制代码
#pragma once
#include<iostream>
using namespace std;

enum color
{
	RED,
	BLACK
};

template<class T>
struct RBTreeNode
{
	T _data;  //_data可以是Key类型的变量,也可以是pair类型的变量
	RBTreeNode<T>* _parent;
	RBTreeNode<T>* _left;
	RBTreeNode<T>* _right;
	color _col;

	RBTreeNode(const T& data)
		:_data(data)
		, _parent(nullptr)
		, _left(nullptr)
		, _right(nullptr)
	{
	}
};
template<class T, class Ref, class Ptr>
struct RBTreeIterator
{
	typedef RBTreeNode<T> Node;
	typedef RBTreeIterator<T, Ref, Ptr> Self;

	Node* _node;
	Node* _root;
	RBTreeIterator(Node* node, Node* root)
		:_node(node)
		, _root(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++()
	{
		if (_node->_right)
		{
			//右不为空,下一个访问的结点是右子树的最左结点
			Node* min = _node->_right;
			while (min->_left)
			{
				min = min->_left;
			}
			_node = min;
		}
		else
		{
			//右为空,下一个是祖先里面孩子是父亲左的那个祖先
			Node* cur = _node;
			Node* parent = cur->_parent;
			while (parent && parent->_right == cur)
			{
				cur = parent;
				parent = parent->_parent;
			}
			_node = parent;
		}
		return *this;
	}
	Self operator--()
	{
		if (_node == nullptr)
		{
			Node* right = _root;
			while (right && right->_right)
			{
				right = right->_right;
			}
			_node = right;
		}
		else if (_node->_left)
		{
			//左子树不为空,下一个是中序左子树的最后一个
			Node* rightMost = _node->_left;
			while (rightMost->_right)
			{
				rightMost = rightMost->_right;
			}
			_node = rightMost;
		}
		else
		{
			//左子树为空,下一个结点是父亲右的那个祖先
			Node* cur = _node;
			Node* parent = cur->_parent;
			while (parent && cur == parent->_left)
			{
				cur = parent;
				parent = cur->_parent;
			}
			_node = parent;
		}
		return *this;
	}
};
template<class K, class T, class KeyofT>
class RBTree
{
	typedef RBTreeNode<T> Node;
public:
	typedef RBTreeIterator<T, T&, T*> Iterator;
	typedef RBTreeIterator<T, const T&, const T*> ConstIterator;
	Iterator Begin()
	{
		Node* cur = _root;
		while (cur && cur->_left)
		{
			cur = cur->_left;
		}
		return Iterator(cur, _root);
	}
	Iterator End()
	{
		return Iterator(nullptr, _root);
	}
	ConstIterator Begin() const
	{
		Node* cur = _root;
		while (cur && cur->_left)
		{
			cur = cur->_left;
		}
		return Iterator(cur, _root);
	}
	ConstIterator End() const
	{
		return Iterator(nullptr, _root);
	}
	void RotateR(Node* parent)
	{
		Node* pParent = parent->_parent;

		Node* subL = parent->_left;
		Node* subLR = subL->_right;

		parent->_left = subLR;
		if (subLR != nullptr)
			subLR->_parent = parent;

		subL->_right = parent;
		parent->_parent = subL;

		if (parent == _root)
		{
			_root = subL;
			subL->_parent = nullptr;
		}
		else
		{
			if (pParent->_left == parent)
			{
				pParent->_left = subL;
			}
			else
			{
				pParent->_right = subL;
			}
			subL->_parent = pParent;
		}
	}
	void RotateL(Node* parent)
	{
		Node* pParent = parent->_parent;
		Node* subR = parent->_right;
		Node* subRL = subR->_left;

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

		subR->_left = parent;
		parent->_parent = subR;

		if (parent == _root)
		{
			_root = subR;
			subR->_parent = nullptr;
		}
		else
		{
			if (pParent->_left == parent)
			{
				pParent->_left = subR;
			}
			else
			{
				pParent->_right = subR;
			}
			subR->_parent = pParent;
		}
	}
	pair<Iterator,bool> Insert(const T& data)
	{
		if (_root == nullptr)
		{
			_root = new Node(data);
			_root->_col = BLACK;
			return pair<Iterator, bool>( Iterator(_root,_root),true );
			//return {iterator(_root,_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 {
				return { Iterator(cur,_root),false };
			}
		}
		cur = new Node(data);
		Node* newnode = cur;//变色旋转之后可能会更新cur
		cur->_col = RED;
		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 (grandfather->_left == parent)
			{
				//   g
				// p  u
				Node* uncle = grandfather->_right;
				if (uncle && uncle->_col == RED)  //叔叔存在,并且叔叔的颜色为红色
				{
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;
					//继续往上处理
					cur = grandfather;
					parent = cur->_parent;
				}
				else   //叔叔不存在或者叔叔的颜色为黑色
				{
					if (cur == parent->_left)
					{
						//    g
						//  p  u
						//c
						RotateR(grandfather);
						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					else
					{
						//    g
						//  p    u
						//	 c
						RotateL(parent);
						RotateR(grandfather);
						cur->_col = BLACK;
						grandfather->_col = RED;
					}
					break;
				}
			}
			else
			{
				//   g
				// u   p
				Node* uncle = grandfather->_left;
				// 叔叔存在切为红,变色即可
				if (uncle && uncle->_col == RED)
				{
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;

					cur = grandfather;
					parent = cur->_parent;
				}
				else
				{
					//    g
					// u     p
					//         c
					if (cur == parent->_right)
					{
						RotateL(grandfather);
						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					else
					{
						//     g
						//   u    p
						//       c
						RotateR(parent);
						RotateL(grandfather);
						cur->_col = BLACK;
						grandfather->_col = RED;
					}
					break;
				}
			}
		}

		_root->_col = BLACK;
		return { Iterator(newnode,_root),true };
	}
	//void InOrder()
	//{
	//	_InOrder(_root);
	//}
	//int Height()
	//{
	//	return _Height(_root);
	//}
	//int Size()
	//{
	//	return _Size(_root);
	//}
	//bool IsBalance()
	//{
	//	if (_root == nullptr)
	//		return true;
	//	if (_root->_col == RED)
	//		return false;
	//	// 参考值
	//	int refNum = 0;
	//	Node* cur = _root;
	//	while (cur)
	//	{
	//		if (cur->_col == BLACK)
	//		{
	//			++refNum;
	//		}
	//		cur = cur->_left;
	//	}
	//	return Check(_root, 0, refNum);
	//}
private:
	Node* _root = nullptr;

	//void _InOrder(Node* root)
	//{
	//	if (root == nullptr)
	//	{
	//		return;
	//	}
	//	_InOrder(root->_left);
	//	cout << root->_kv.first << "::" << root->_kv.second << endl;
	//	_InOrder(root->_right);
	//}
	//int _Height(Node* root)
	//{
	//	if (root == 0)
	//		return 0;
	//	int leftHeight = _Height(root->_left);
	//	int rightHeight = _Height(root->_right);
	//	return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
	//}
	//int _Size(Node* root)
	//{
	//	if (root == 0)
	//		return 0;
	//	return _Size(root->_left) + _Size(root->_right) + 1;
	//}
	//bool Check(Node* root, int blackNum, const int refNum)
	//{
	//	if (root == nullptr)
	//	{
	//		// 前序遍历走到空时,意味着一条路径走完了
	//		//cout << blackNum << endl;
	//		if (refNum != blackNum)
	//		{
	//			cout << "存在黑色结点的数量不相等的路径" << endl;
	//			return false;
	//		}
	//		return true;
	//	}
	//	// 检查孩子不太方便,因为孩子有两个,且不一定存在,反过来检查父亲就方便多了
	//	if (root->_col == RED && root->_parent->_col == RED)
	//	{
	//		cout << root->_kv.first << "存在连续的红色结点" << endl;
	//		return false;
	//	}
	//	if (root->_col == BLACK)
	//	{
	//		blackNum++;
	//	}
	//	return Check(root->_left, blackNum, refNum)
	//		&& Check(root->_right, blackNum, refNum);
	//}
};

7.2 mymap.h

cpp 复制代码
#pragma once
#pragma once
#include"RBTree.h"

namespace zx
{
	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>::ConstIterator 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();
		}
		pair<iterator,bool> insert(const pair<K, V>& kv)
		{
			return _t.Insert(kv);
		}
		V& operator[](const K& key)
		{
			pair<iterator, bool> ret = insert({ key,V() });
			return ret.first->second;
		}
	private:
		RBTree<K, pair<const K, V>, MapKeyOfT> _t;
	};
}

7.3 myset.h

cpp 复制代码
#pragma once
#pragma once
#include"RBTree.h"

namespace zx
{
	template<class K>
	class set
	{
		struct SetKeyOfT
		{
			const K& operator()(const K& key)
			{
				return key;
			}
		};
	public:
		typedef typename RBTree<K, const K, SetKeyOfT>::Iterator iterator;
		typedef typename RBTree<K, const K, SetKeyOfT>::ConstIterator 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();
		}
		pair<iterator, bool> insert(const K& key)
		{
			return _t.Insert(key);
		}
	private:
		RBTree<K, const K, SetKeyOfT> _t;
	};
}

7.4 test.cpp

cpp 复制代码
#include<string>
#include"myset.h"
#include"mymap.h"
#include"RBTree.h"

void testset()
{
	zx::set<int> s;
	s.insert(5);
	s.insert(1);
	s.insert(3);
	s.insert(2);
	s.insert(6);
	zx::set<int>::iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
}
void testmap()
{
	zx::map<string, string> dict;
	dict.insert({ "left","左边" });
	dict.insert({ "right","右边" });
	dict.insert({ "sort","排序" });
	dict.insert({ "auto","自动" });
	zx::map<string, string>::iterator it = dict.begin();
	while (it != dict.end())
	{
		//it->first += 'x';
		//it->second += 'x';
		cout << it->first << "::" << it->second << endl;
		++it;
	}
	cout << endl;
}
void testset1()
{
	zx::set<int> s;
	s.insert(5);
	s.insert(1);
	s.insert(3);
	s.insert(2);
	s.insert(6);
	zx::set<int>::iterator it = s.end();
	while (it != s.begin())
	{
		--it;
		cout << *it << " ";
	}
	cout << endl;
}
void testmap1()
{
	zx::map<string, string> dict;
	dict.insert({ "left","左边" });
	dict.insert({ "right","右边" });
	dict.insert({ "sort","排序" });
	dict.insert({ "auto","自动" });
	zx::map<string, string>::iterator it = dict.begin();
	while (it != dict.end())
	{

		cout << it->first << "::" << it->second << endl;
		++it;
	}
	cout << endl;
	dict["left"] = "右边,剩余";
	dict["insert"] = "插入";
	dict["string"];
	it = dict.begin();
	while (it != dict.end())
	{

		cout << it->first << "::" << it->second << endl;
		++it;
	}
	cout << endl;
	
}
int main()
{
	//testset();
	//testmap();
	//testset1();
	testmap1();
	return 0;
}
相关推荐
满天星83035772 小时前
【Linux/多路复用】select
linux·运维·服务器·c语言·c++
t***5442 小时前
如何验证Clang是否在Dev-C++中正常工作
开发语言·c++
charlie1145141912 小时前
嵌入式C++开发第17篇:C++23特性收尾 —— 属性、链接与零开销抽象的最终证明
开发语言·c++·stm32·学习·c++23
小成202303202652 小时前
数据结构(整理常见结构总结到树层级)
java·c语言·数据结构·c++·链表
ximu_polaris2 小时前
设计模式(C++)-结构型模式-外观模式
c++·设计模式·外观模式
Xiu Yan2 小时前
Java 转 C++ 系列:STL常用函数
java·开发语言·c++·stl·visual studio
沫璃染墨3 小时前
C++ std::list 深度解析:迭代器、splice 核心接口与排序效率全解
开发语言·c++
艾莉丝努力练剑3 小时前
【Linux网络】计算机网络入门:从背景到协议,理解网络通信基础
linux·运维·服务器·c++·学习·计算机网络
艾莉丝努力练剑3 小时前
【Linux线程】Linux系统多线程(十):线程安全和重入、死锁相关话题
java·linux·运维·服务器·c++·学习·安全