AVL,红黑树,map和set的分装

前言

这一篇博客我会给出AVL,红黑树,map和set的分装的代码

1. AVL树


//实现AVL树
template<class K>
struct BSNode
{
	BSNode<K>* _left;
	BSNode<K>* _right;
	BSNode<K>* _parent;
	int _bf;
	K _key;
	typedef BSNode<K> Node;
	BSNode(const K& key)
		:_key(key)
		, _left(nullptr)
		, _right(nullptr)
		,_parent(nullptr)
		,_bf(0)//右子树高度减左子树高度
	{}
};

template<class K>
class BSTree
{
public:
	typedef BSNode<K> Node;

	bool insert(const K& key)
	{
		if (_root == nullptr)
		{
			_root = new Node(key);
			return true;
		}
		Node* cur = _root;
		Node* parent = nullptr;
		while (cur)
		{
			if (key > cur->_key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (key < cur->_key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return false;
			}
		}
		cur = new Node(key);
		//但要注意_root==nullptr的时候
		if (key > parent->_key)
		{
			parent->_right = cur;
			cur->_parent = parent;
		}
		else
		{
			parent->_left = cur;
			cur->_parent = parent;
		}
		//插入完成,开始检查是否平衡
		while (cur!=_root)
		{
			//对于最初的和需要调整_bf的,遵循这个规则,插入右边,_bf就加加,插入左边就减减
			if (parent->_left == cur)
			{
				parent->_bf--;
			}
			else if (parent->_right == cur)
			{
				parent->_bf++;
			}

			//如果parent的bf为0,就不用调整了//因为这个说明子树高度不变
			if (parent->_bf == 0)
			{
				break;
			}

			//如果parent的bf为1,就要调整了,而且就是最初的那样调整//因为这个说明子树长高了
			if (parent->_bf == -1 || parent->_bf == 1)
			{
				cur = parent;
				if (parent->_parent)
				{
					parent = parent->_parent;
				}
			}

			//这样就需要调整了
			if (parent->_bf == -2 || parent->_bf == 2)
			{
				if (parent->_bf == 2 && cur->_bf == 1)//RR型
				{
					RR(parent);
				}
				else if (parent->_bf == -2 && cur->_bf == -1)//LL型
				{
					LL(parent);
				}
				else if (parent->_bf == 2 && cur->_bf == -1)//RL
				{
					RL(parent);
				}
				else if (parent->_bf == -2 && cur->_bf == 1)//LR
				{
					LR(parent);
				}
				else
				{
					assert(false);
				}
				break;//因为旋转之后高度降低了,或者说,高度恢复到以前的状态了,所以就平衡了,不用在调节了
				//而删除就不一定了,因为本来就删除高度可能减了,旋转之后又减了,没有恢复到以前的状态,所以还可能多次旋转
			}
		}
		return true;
	}

	//写个中序遍历
	//_root是this指针里面的东西,所以不好搞,不好递归,所以采用调用函数的方法
	void InOrder()
	{
		_InOrder(_root);
		cout << endl;
	}

	void PreOrder()
	{
		_PreOrder(_root);
		cout << endl;
	}


	//搜索某个数据
	Node* Search(const K& key)
	{
		Node* cur = _root;
		Node* parent = nullptr;
		while (cur)
		{
			if (key > cur->_key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (key < cur->_key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return cur;
			}
		}
		return nullptr;
	}

	//删除某个数据
	bool Erase(const K& key)
	{
		if (_root == nullptr)
		{
			return false;
		}
		Node* cur = _root;
		Node* parent = nullptr;
		while (cur)
		{
			if (key > cur->_key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (key < cur->_key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				//找到了要删除的数据
				//删除的话就分为三种//
				//第一种就是没有孩子直接删除
				//第二种就是有一个孩子的话就直接连在父亲的后面
				//第三种就是有两个孩子
				//其中第一种和第二种可以合并。因为可以把没有孩子当做空指针的孩子
				if (cur->_left == nullptr)
				{
					if (parent == nullptr)//说明删的是根
					{
						_root = cur->_right;
						delete cur;
						return true;
					}
					//先看cur在parent的左还是右
					if (cur->_key < parent->_key)
					{
						parent->_left = cur->_right;
					}
					else
					{
						parent->_right = cur->_right;
					}
					delete cur;
					return true;
				}
				else if (cur->_right == nullptr)
				{
					if (parent == nullptr)//说明删的是根
					{
						_root = cur->_left;
						delete cur;
						return true;
					}
					if (cur->_key < parent->_key)
					{
						parent->_left = cur->_left;
					}
					else
					{
						parent->_right = cur->_left;
					}
					delete cur;
					return true;
				}
				else//现在左右孩子都不为空
				{
					//如果是头结点,也不用单独考虑,我们这样设计的话
					//我们直接找到右孩子的最小值放在cur,然后删除这个最小值节点就可以了,最小值就是一直往左走就可以了
					Node* min = cur->_right;
					Node* min_parent = cur;
					while (min->_left)
					{
						min_parent = min;
						min = min->_left;
					}
					cur->_key = min->_key;
					//删除min节点
					//因为min的左孩子一定为空,所以很好删除
					if (min_parent == cur)//说明没走
					{
						min_parent->_right = min->_right;
					}
					else
					{
						min_parent->_left = min->_right;
					}
					delete min;
					return true;
				}
			}
		}
		return false;
	}

	bool IsBalance()
	{
		return _IsBalance(_root);
	}

private:
	void RR(Node* parent)
	{
		Node* parent_parent = parent->_parent;
		Node* subR = parent->_right;
		Node* subRL = subR->_left;
		//开始链接左右孩子
		parent->_right = subRL;
		subR->_left = parent;
		if (parent_parent)
		{
			if (parent_parent->_left == parent)
			{
				parent_parent->_left = subR;
			}
			else
			{
				parent_parent->_right = subR;
			}
		}
		else//说明parent_parent是nullptr,parent就是_root了
		{
			_root = subR;
		}
		//开始链接父亲节点
		if(subRL)//防止RL的时候调用为空,因为RL的时候调用的parent不是2或-2
		subRL->_parent = parent;
		parent->_parent = subR;
		subR->_parent = parent_parent;
		//开始修改_bf
		parent->_bf = 0;
		subR->_bf = 0;
	}

	void LL(Node* parent)//就是在RR的核心逻辑上right改left,left改right
	{
		Node* parent_parent = parent->_parent;
		Node* subR = parent->_left;
		Node* subRL = subR->_right;
		//开始链接左右孩子
		parent->_left = subRL;
		subR->_right = parent;
		if (parent_parent)
		{
			if (parent_parent->_left == parent)
			{
				parent_parent->_left = subR;
			}
			else
			{
				parent_parent->_right = subR;
			}
		}
		else//说明parent_parent是nullptr,parent就是_root了
		{
			_root = subR;
		}
		//开始链接父亲节点
		if(subRL)
		subRL->_parent = parent;
		parent->_parent = subR;
		subR->_parent = parent_parent;
		//开始修改_bf
		parent->_bf = 0;
		subR->_bf = 0;
	}

	void RL(Node* parent)
	{
		//先记录三个特殊的节点
		Node* subR = parent->_right;
		Node* subRL = subR->_left;
		int tmp = subRL->_bf;
		//这个的话,就是先将parent->right用LL处理,再用parent用RR处理
		LL(parent->_right);
		RR(parent);
		//但是这样还不行,因为这样处理后全部的_bf都变为了0,这样是不行的,因为parent->right的_bf不为2或-2,所以这样处理会有问题
		if (tmp == 0)//说明它没有孩子,如果有孩子的话,就插入不会不平衡
		{
			parent->_bf = 0;
			subR->_bf = 0;
			subRL->_bf = 0;
		}
		else if (tmp == -1)
		{
			parent->_bf = 0;
			subR->_bf = 1;
			subRL->_bf = 0;
		}
		else if (tmp == 1)
		{
			parent->_bf = -1;
			subR->_bf = 0;
			subRL->_bf = 0;
		}
	}

	void LR(Node* parent)//还是一样的,right改left,left改right
	{
		//先记录三个特殊的节点
		Node* subL = parent->_left;
		Node* subLR = subL->_right;
		int tmp = subLR->_bf;
		//这个的话,就是先将parent->right用LL处理,再用parent用RR处理
		RR(parent->_left);
		LL(parent);
		//但是这样还不行,因为这样处理后全部的_bf都变为了0,这样是不行的,因为parent->right的_bf不为2或-2,所以这样处理会有问题
		//if (subLR->_bf == 0)//说明它没有孩子,如果有孩子的话,就插入不会不平衡
			//还不能这样讨论,因为已经改为0了,应该提前记录
		if(tmp==0)
		{
			parent->_bf = 0;
			subL->_bf = 0;
			subLR->_bf = 0;
		}
		else if (tmp == -1)
		{
			parent->_bf = 0;
			subL->_bf = 1;
			subLR->_bf = 0;
		}
		else if (tmp == 1)
		{
			parent->_bf = -1;
			subL->_bf = 0;
			subLR->_bf = 0;
		}
	}

	void _InOrder(Node* root)
	{
		if (root == nullptr)
		{
			return;
		}
		_InOrder(root->_left);
		cout << root->_key << " ";
		_InOrder(root->_right);
	}

	void _PreOrder(Node* root)
	{
		if (root == nullptr)
		{
			return;
		}
		cout << root->_key << " ";
		_PreOrder(root->_left);
		_PreOrder(root->_right);
	}
	
	int GetHeight(Node*root)
	{
		if (root == nullptr)
		{
			return 0;
		}
		int h1 = GetHeight(root->_left);
		int h2 = GetHeight(root->_right);
		return h1 > h2 ? (h1 + 1) : (h2 + 1);
	}
	
	bool _IsBalance(Node* root)
	{
		if (root == nullptr)
		{
			return true;
		}
		//判断一个树是不是平衡树,先看这个节点的左右子树高度差绝对值是不是小于2,而且等于_bf
		//然后就是左右子树均为平衡树
		int h1 = GetHeight(root->_left);
		int h2 = GetHeight(root->_right);
		int dif = h2 - h1;
		int BigDif = abs(dif);
		if (BigDif >= 2 )
		{
			cout << "hahah" << endl;
			return false;
		}
		if (dif != root->_bf)
		{
			cout << root->_bf << endl;
			cout << dif << endl;
			cout << root->_key << endl;
			cout << "hhhh" << endl;
			return false;
		}
		return _IsBalance(root->_left) && _IsBalance(root->_right);
	}

	Node* _root = nullptr;
};

2. 红黑树


enum color
{
	Red,
	Black
};

//实现AVL树
template<class K>
struct BRNode
{
	BRNode<K>* _left;
	BRNode<K>* _right;
	BRNode<K>* _parent;
	K _key;
	color _color;
	typedef BRNode<K> Node;
	BRNode(const K& key)
		:_key(key)
		, _left(nullptr)
		, _right(nullptr)
		, _parent(nullptr)
		,_color(Red)
	{}
};

template<class K>
class BRTree
{
public:
	typedef BRNode<K> Node;

	bool insert(const K& key)
	{
		if (_root == nullptr)
		{
			_root = new Node(key);
			_root->_color = Black;
			return true;
		}
		Node* cur = _root;
		Node* parent = nullptr;
		while (cur)
		{
			if (key > cur->_key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (key < cur->_key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return false;
			}
		}
		cur = new Node(key);
		//但要注意_root==nullptr的时候
		if (key > parent->_key)
		{
			parent->_right = cur;
			cur->_parent = parent;
		}
		else
		{
			parent->_left = cur;
			cur->_parent = parent;
		}

		//插入完成,开始检查是否平衡
		while (parent&&parent->_color==Red)//红黑树总共有四个特性,
			//左小于根小于右(左跟右),一条路黑相同(黑路同),根为黑(根叶黑),然后就是连续的不为红(不红红)
		//插入只会不红红特性
		{
			//先找到叔叔parent->_color==Red说明一定有爷
			Node* Grandparent = parent->_parent;
			if (parent == Grandparent->_right)
			{
				//叔叔在左边
				Node* uncle = Grandparent->_left;
				//开始讨论叔叔为红还是黑//叔叔为空默认为黑
				if (uncle && uncle->_color == Red)
				{
					//只需要将叔叔父亲变黑,爷爷变红就可以了
					uncle->_color = Black;
					parent->_color = Black;
					Grandparent->_color = Red;
					//然后将Grandparent看为cur继续循环
					cur = Grandparent;
					parent = cur->_parent;
					//当parent为红就继续循环
					//如果为空,说明cur为根,所以直接退出循环变黑,并增加条件parent不为空
				}
				else if (!uncle || uncle->_color == Black)//叔叔为空或者为黑//而且叔叔为黑这种情况只可能是由叔叔为红变过来的,不可能一开始插入就变成这样了
					//因为不满足黑路同,所以cur还有子树,后面还有黑节点
				{
					//接下来就来看是什么类型的旋转
					if (cur == parent->_right)//RR
					{
						RR(Grandparent);
						//然后再让原来的爷爷变红,原来的父亲变黑,原来的父亲就变为爷爷
						Grandparent->_color = Red;
						parent->_color = Black;
						//因为原来的父亲就变为爷爷,爷爷变黑,所以黑色节点每条路还是相同的,反正就是旋转之后就已经满足了红黑树了
						//不需要在继续循环了
						break;
					}
					else//RL
					{
						LL(parent);
						RR(Grandparent);
						//cur变黑,Grandparent变红
						cur->_color = Black;
						Grandparent->_color = Red;
						break;
					}
				}
			}
			else
			{
				Node* uncle = Grandparent->_right;
				//开始讨论叔叔为红还是黑//叔叔为空默认为黑
				if (uncle && uncle->_color == Red)
				{
					//只需要将叔叔父亲变黑,爷爷变红就可以了
					uncle->_color = Black;
					parent->_color = Black;
					Grandparent->_color = Red;
					//然后将Grandparent看为cur继续循环
					cur = Grandparent;
					parent = cur->_parent;
					//当parent为红就继续循环
					//如果为空,说明cur为根,所以直接退出循环变黑,并增加条件parent不为空
				}
				else if (!uncle || uncle->_color == Black)//叔叔为空或者为黑//而且叔叔为黑这种情况只可能是由叔叔为红变过来的,不可能一开始插入就变成这样了
					//因为不满足黑路同,所以cur还有子树,后面还有黑节点
				{
					//接下来就来看是什么类型的旋转
					if (cur == parent->_left)//LL
					{
						LL(Grandparent);
						//然后再让原来的爷爷变红,原来的父亲变黑,原来的父亲就变为爷爷
						Grandparent->_color = Red;
						parent->_color = Black;
						//因为原来的父亲就变为爷爷,爷爷变黑,所以黑色节点每条路还是相同的,反正就是旋转之后就已经满足了红黑树了
						//不需要在继续循环了
						break;
					}
					else//LR
					{
						RR(parent);
						LL(Grandparent);
						//cur变黑,Grandparent变红
						cur->_color = Black;
						Grandparent->_color = Red;
						break;
					}
				}
			}
		}
		_root->_color = Black;
		return true;
	}

	void InOrder()
	{
		_InOrder(_root);
		cout << endl;
	}

	void PreOrder()
	{
		_PreOrder(_root);
		cout << endl;
	}

	bool IsBalance()
	{
		return _IsBalance(_root);
	}
	//搜索某个数据
	Node* Search(const K& key)
	{
		Node* cur = _root;
		Node* parent = nullptr;
		while (cur)
		{
			if (key > cur->_key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (key < cur->_key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return cur;
			}
		}
		return nullptr;
	}

	//删除某个数据
	bool Erase(const K& key)
	{
		if (_root == nullptr)
		{
			return false;
		}
		Node* cur = _root;
		Node* parent = nullptr;
		while (cur)
		{
			if (key > cur->_key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (key < cur->_key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				//找到了要删除的数据
				//删除的话就分为三种//
				//第一种就是没有孩子直接删除
				//第二种就是有一个孩子的话就直接连在父亲的后面
				//第三种就是有两个孩子
				//其中第一种和第二种可以合并。因为可以把没有孩子当做空指针的孩子
				if (cur->_left == nullptr)
				{
					if (parent == nullptr)//说明删的是根
					{
						_root = cur->_right;
						delete cur;
						return true;
					}
					//先看cur在parent的左还是右
					if (cur->_key < parent->_key)
					{
						parent->_left = cur->_right;
					}
					else
					{
						parent->_right = cur->_right;
					}
					delete cur;
					return true;
				}
				else if (cur->_right == nullptr)
				{
					if (parent == nullptr)//说明删的是根
					{
						_root = cur->_left;
						delete cur;
						return true;
					}
					if (cur->_key < parent->_key)
					{
						parent->_left = cur->_left;
					}
					else
					{
						parent->_right = cur->_left;
					}
					delete cur;
					return true;
				}
				else//现在左右孩子都不为空
				{
					//如果是头结点,也不用单独考虑,我们这样设计的话
					//我们直接找到右孩子的最小值放在cur,然后删除这个最小值节点就可以了,最小值就是一直往左走就可以了
					Node* min = cur->_right;
					Node* min_parent = cur;
					while (min->_left)
					{
						min_parent = min;
						min = min->_left;
					}
					cur->_key = min->_key;
					//删除min节点
					//因为min的左孩子一定为空,所以很好删除
					if (min_parent == cur)//说明没走
					{
						min_parent->_right = min->_right;
					}
					else
					{
						min_parent->_left = min->_right;
					}
					delete min;
					return true;
				}
			}
		}
		return false;
	}

private:
	void RR(Node* parent)
	{
		Node* parent_parent = parent->_parent;
		Node* subR = parent->_right;
		Node* subRL = subR->_left;
		//开始链接左右孩子
		parent->_right = subRL;
		subR->_left = parent;
		if (parent_parent)
		{
			if (parent_parent->_left == parent)
			{
				parent_parent->_left = subR;
			}
			else
			{
				parent_parent->_right = subR;
			}
		}
		else//说明parent_parent是nullptr,parent就是_root了
		{
			_root = subR;
		}
		//开始链接父亲节点
		if (subRL)//防止RL的时候调用为空,因为RL的时候调用的parent不是2或-2
			subRL->_parent = parent;
		parent->_parent = subR;
		subR->_parent = parent_parent;
	}

	void LL(Node* parent)//就是在RR的核心逻辑上right改left,left改right
	{
		Node* parent_parent = parent->_parent;
		Node* subR = parent->_left;
		Node* subRL = subR->_right;
		//开始链接左右孩子
		parent->_left = subRL;
		subR->_right = parent;
		if (parent_parent)
		{
			if (parent_parent->_left == parent)
			{
				parent_parent->_left = subR;
			}
			else
			{
				parent_parent->_right = subR;
			}
		}
		else//说明parent_parent是nullptr,parent就是_root了
		{
			_root = subR;
		}
		//开始链接父亲节点
		if (subRL)
			subRL->_parent = parent;
		parent->_parent = subR;
		subR->_parent = parent_parent;
	}

	void _InOrder(Node* root)
	{
		if (root == nullptr)
		{
			return;
		}
		_InOrder(root->_left);
		cout << root->_key << " ";
		_InOrder(root->_right);
	}

	void _PreOrder(Node* root)
	{
		if (root == nullptr)
		{
			return;
		}
		cout << root->_key << " ";
		_PreOrder(root->_left);
		_PreOrder(root->_right);
	}

	bool _Judge1(Node* root, int min, int max)
	{
		if (root == nullptr)
		{
			return true;
		}
		if (!(root->_key >= min && root->_key <= max))
		{
			return false;
		}
		return _Judge1(root->_left, min, root->_key) && _Judge1(root->_right, root->_key, max);//往左走min保留,往右走max保留
	}

	bool Judge1(Node* root)
	{
		if (root == nullptr)
		{
			return true;
		}
		//这个就是判断一个树是不是搜索树罢了
		//直接先序遍历,传入区间进去,值不满足上个父亲传下来的区间就是false
		return _Judge1(root->_left,INT_MIN, root->_key) && _Judge1(root->_right, root->_key, INT_MAX);//这里的区间很难处理,所以我们
		//定义一个很大的数,很很小的数
	}

	//bool Judge24(Node* root, int BlackNum, int num)
	//{
	//	//我们用一个BlackNum来记录根节点到此节点的黑色节点数量
	//	//如何检验黑路同呢
	//	//对于一个节点来讲,它到任意叶子的黑色数量相同,然后左右子树也是这样,终止条件就是为null时,看数量是不是num
	//	if (root == nullptr)
	//	{
	//		if (num != BlackNum)
	//		{
	//			return false;
	//		}
	//		return true;
	//	}
	//	if (root->_color == Black)
	//	{
	//		BlackNum++;
	//	}
	//	return Judge24(root->_left, BlackNum, num) && Judge24(root->_right, BlackNum, num);
	//}
	// 或许我们可以这样理解,我们来实现一个先序遍历,一边遍历,一遍统计到此节点的黑色数量,到了空节点就判断一下,然后只要有一个地方不满足,就总的是
	// false了,所以先序遍历间用的是&&
	//然后我们在增加不红红的判断,就是在遍历的过程中看看如果自己为红,再看看父亲为不为红

	bool Judge24(Node* root, int BlackNum, int num)
	{
		//我们用一个BlackNum来记录根节点到此节点的黑色节点数量
		//如何检验黑路同呢
		//对于一个节点来讲,它到任意叶子的黑色数量相同,然后左右子树也是这样,终止条件就是为null时,看数量是不是num
		if (root == nullptr)
		{
			if (num != BlackNum)
			{
				return false;
			}
			return true;
		}
		if (root->_color == Black)
		{
			BlackNum++;
		}
		else
		{
			if (root->_parent && root->_parent->_color == Red)
			{
				return false;
			}
		}
		return Judge24(root->_left, BlackNum, num) && Judge24(root->_right, BlackNum, num);
	}

	bool _IsBalance(Node* root)//这个函数来判断是不是红黑树
		//红黑树总共有四个特性,挨个挨个判断就可以了
		//左小于根小于右(左跟右),一条路黑相同(黑路同),根为黑(根叶黑),然后就是连续的不为红(不红红)
	{
		//根叶黑
		if (_root->_color == Red)
		{
			return false;
		}

		//先统计好根到随便一个叶子结点的黑色节点数目
		int num = 0;
		Node * cur = _root;
		while (cur)
		{
			if (cur->_color == Black)
			{
				num++;
			}
			cur = cur->_left;
		}

		return Judge24(root,0,num)&& Judge1(root);
	}

	Node* _root = nullptr;
};

3. map和set的分装

3.1 BRTree.h


namespace bit
{
	enum color
	{
		Red,
		Black
	};

	//实现AVL树
	template<class T>//T可能是key也可能是pair
	struct BRNode
	{
		BRNode<T>* _left;
		BRNode<T>* _right;
		BRNode<T>* _parent;
		T _kv;
		color _color;
		BRNode(const T& kv)
			:_kv(kv)
			, _left(nullptr)
			, _right(nullptr)
			, _parent(nullptr)
			, _color(Red)
		{}
	};

	template<class T,class l1,class l2>
	struct BRIterator
	{
		typedef BRIterator<T,l1,l2> self;

		typedef BRNode<T> Node;

		BRIterator(Node*tmp,Node*root)//C++中,‌构造函数的名字不可以是typedef出来的。‌所以不能用self的名字来构造
			:_node(tmp)
			,_root(root)
		{}

		self&operator++()
		{
			//找任意一个节点在中序遍历中的下一个节点,分为两种情况,有右子树,和没有右子树
			if (_node->_right)
			{
				//就找右子树的最左边那个节点
				Node* cur = _node->_right;
				while (cur->_left)
				{
					cur = cur->_left;
				}
				_node = cur;
				return *this;
			}
			else
			{
				//从该节点开始定义父节点和子节点,如果子节点是父节点的右孩子就继续往上找,左孩子就退出,并返回父节点
				Node* cur = _node;
				Node* parent = _node->_parent;
				while (parent&& parent->_right == cur)//防止到了最后头结点
				{
					cur = parent;
					parent = parent->_parent;
				}
				_node = parent;
				return *this;
			}
		}

		self& operator--()//这个与++就完全相反了,因为++是左中右,那么减减就是右中左,只需要左换右,右换左就可以了
		{
			//但万一_node是nullptr呢
			if (_node == nullptr)
			{
				//直接让Node=end就可以了,就是最右边那个
				//所以还要传入root
				Node* cur = _root;
				while (cur && cur->_right)
				{
					cur = cur->_right;
				}
				_node = cur;
				return *this;
			}
			if (_node->_left)
			{
				//就找右子树的最左边那个节点
				Node* cur = _node->_left;
				while (cur&&cur->_right)
				{
					cur = cur->_right;
				}
				_node = cur;
				return *this;
			}
			else
			{
				Node* cur = _node;
				Node* parent = _node->_parent;
				while (parent && parent->_left == cur)
				{
					cur = parent;
					parent = parent->_parent;
				}
				_node = parent;
				return *this;
			}
		}

		l1 operator*()
		{
			return _node->_kv;
		}

		l2 operator->()
		{
			return &_node->_kv;
		}

		bool operator==(const self& se)
		{
			return _node == se._node;
		}

		bool operator!=(const self& se)//最好都写上const,因为end函数出来的是临时变量
		{
			return _node != se._node;
		}

		Node* _node;
		Node* _root;
	};

	template<class K, class T,class KeyOfT>
	class BRTree
	{
	public:
		typedef BRNode<T> Node;
		typedef BRIterator<T,T&,T*> self;
		typedef BRIterator<T,const T&,const T*> const_self;

		pair<self,bool> Insert(const T& kv)
		{
			if (_root == nullptr)
			{
				_root = new Node(kv);
				_root->_color = Black;
				return make_pair(self(_root,_root), true);
			}
			KeyOfT kof;
			Node* cur = _root;
			Node* parent = nullptr;
			while (cur)
			{
				if (kof(kv) > kof(cur->_kv))//但是这里针对pair的比较又不行了,所以我们要改造函数//因为比较的是K
				{
					parent = cur;
					cur = cur->_right;
				}
				else if (kof(kv) < kof(cur->_kv))
				{
					parent = cur;
					cur = cur->_left;
				}
				else
				{
					return make_pair(self(cur,_root), false);
				}
			}
			cur = new Node(kv);
			Node* ret = cur;
			//但要注意_root==nullptr的时候
			if (kof(kv) > kof(parent->_kv))
			{
				parent->_right = cur;
				cur->_parent = parent;
			}
			else
			{
				parent->_left = cur;
				cur->_parent = parent;
			}

			//插入完成,开始检查是否平衡
			while (parent && parent->_color == Red)//红黑树总共有四个特性,
				//左小于根小于右(左跟右),一条路黑相同(黑路同),根为黑(根叶黑),然后就是连续的不为红(不红红)
			//插入只会不红红特性
			{
				//先找到叔叔parent->_color==Red说明一定有爷
				Node* Grandparent = parent->_parent;
				if (parent == Grandparent->_right)
				{
					//叔叔在左边
					Node* uncle = Grandparent->_left;
					//开始讨论叔叔为红还是黑//叔叔为空默认为黑
					if (uncle && uncle->_color == Red)
					{
						//只需要将叔叔父亲变黑,爷爷变红就可以了
						uncle->_color = Black;
						parent->_color = Black;
						Grandparent->_color = Red;
						//然后将Grandparent看为cur继续循环
						cur = Grandparent;
						parent = cur->_parent;
						//当parent为红就继续循环
						//如果为空,说明cur为根,所以直接退出循环变黑,并增加条件parent不为空
					}
					else if (!uncle || uncle->_color == Black)//叔叔为空或者为黑//而且叔叔为黑这种情况只可能是由叔叔为红变过来的,不可能一开始插入就变成这样了
						//因为不满足黑路同,所以cur还有子树,后面还有黑节点
					{
						//接下来就来看是什么类型的旋转
						if (cur == parent->_right)//RR
						{
							RR(Grandparent);
							//然后再让原来的爷爷变红,原来的父亲变黑,原来的父亲就变为爷爷
							Grandparent->_color = Red;
							parent->_color = Black;
							//因为原来的父亲就变为爷爷,爷爷变黑,所以黑色节点每条路还是相同的,反正就是旋转之后就已经满足了红黑树了
							//不需要在继续循环了
							break;
						}
						else//RL
						{
							LL(parent);
							RR(Grandparent);
							//cur变黑,Grandparent变红
							cur->_color = Black;
							Grandparent->_color = Red;
							break;
						}
					}
				}
				else
				{
					Node* uncle = Grandparent->_right;
					//开始讨论叔叔为红还是黑//叔叔为空默认为黑
					if (uncle && uncle->_color == Red)
					{
						//只需要将叔叔父亲变黑,爷爷变红就可以了
						uncle->_color = Black;
						parent->_color = Black;
						Grandparent->_color = Red;
						//然后将Grandparent看为cur继续循环
						cur = Grandparent;
						parent = cur->_parent;
						//当parent为红就继续循环
						//如果为空,说明cur为根,所以直接退出循环变黑,并增加条件parent不为空
					}
					else if (!uncle || uncle->_color == Black)//叔叔为空或者为黑//而且叔叔为黑这种情况只可能是由叔叔为红变过来的,不可能一开始插入就变成这样了
						//因为不满足黑路同,所以cur还有子树,后面还有黑节点
					{
						//接下来就来看是什么类型的旋转
						if (cur == parent->_left)//LL
						{
							LL(Grandparent);
							//然后再让原来的爷爷变红,原来的父亲变黑,原来的父亲就变为爷爷
							Grandparent->_color = Red;
							parent->_color = Black;
							//因为原来的父亲就变为爷爷,爷爷变黑,所以黑色节点每条路还是相同的,反正就是旋转之后就已经满足了红黑树了
							//不需要在继续循环了
							break;
						}
						else//LR
						{
							RR(parent);
							LL(Grandparent);
							//cur变黑,Grandparent变红
							cur->_color = Black;
							Grandparent->_color = Red;
							break;
						}
					}
				}
			}
			_root->_color = Black;
			return make_pair(self(ret, _root), true);
		}

		//搜索某个数据
		Node* Search(const T& key)
		{
			KeyOfT kof;
			Node* cur = _root;
			Node* parent = nullptr;
			while (cur)
			{
				if (kof(key) > kof(cur->_kv))
				{
					parent = cur;
					cur = cur->_right;
				}
				else if (kof(key) < kof(cur->_kv))
				{
					parent = cur;
					cur = cur->_left;
				}
				else
				{
					return cur;
				}
			}
			return nullptr;
		}

		void InOrder()
		{
			_InOrder(_root);
			cout << endl;
		}

		//迭代器
		self Begin()
		{
			//找到最左边的节点就可以了
			Node* cur = _root;
			while (cur&&cur->_left)
			{
				cur = cur->_left;
			}
			return self(cur,_root);
		}

		self End()
		{
			return self(nullptr,_root);//我们以空指针作为end
		}

		const_self Begin()const
		{
			//找到最左边的节点就可以了
			Node* cur = _root;
			while (cur && cur->_left)
			{
				cur = cur->_left;
			}
			return const_self(cur, _root);
		}

		const_self End()const
		{
			return const_self(nullptr, _root);//我们以空指针作为end
		}

	private:
		void RR(Node* parent)
		{
			Node* parent_parent = parent->_parent;
			Node* subR = parent->_right;
			Node* subRL = subR->_left;
			//开始链接左右孩子
			parent->_right = subRL;
			subR->_left = parent;
			if (parent_parent)
			{
				if (parent_parent->_left == parent)
				{
					parent_parent->_left = subR;
				}
				else
				{
					parent_parent->_right = subR;
				}
			}
			else//说明parent_parent是nullptr,parent就是_root了
			{
				_root = subR;
			}
			//开始链接父亲节点
			if (subRL)//防止RL的时候调用为空,因为RL的时候调用的parent不是2或-2
				subRL->_parent = parent;
			parent->_parent = subR;
			subR->_parent = parent_parent;
		}

		void _InOrder(Node* root)
		{
			if (root == nullptr)
			{
				return;
			}
			_InOrder(root->_left);
			KeyOfT k;
			cout << k(root->_kv)<< " ";
			//cout << root->_kv.first;//不能这样因为不知道kv是个啥
			_InOrder(root->_right);
		}

		void LL(Node* parent)//就是在RR的核心逻辑上right改left,left改right
		{
			Node* parent_parent = parent->_parent;
			Node* subR = parent->_left;
			Node* subRL = subR->_right;
			//开始链接左右孩子
			parent->_left = subRL;
			subR->_right = parent;
			if (parent_parent)
			{
				if (parent_parent->_left == parent)
				{
					parent_parent->_left = subR;
				}
				else
				{
					parent_parent->_right = subR;
				}
			}
			else//说明parent_parent是nullptr,parent就是_root了
			{
				_root = subR;
			}
			//开始链接父亲节点
			if (subRL)
				subRL->_parent = parent;
			parent->_parent = subR;
			subR->_parent = parent_parent;
		}

		Node* _root = nullptr;
	};
}

3.2 set.h


namespace bit
{
	template<class K>
	class set
	{
	public:
		struct KeyOf
		{
			K operator()(const K& k)
			{
				return k;
			}
		};

		//typedef bit::BRIterator< K, const K&, const K*> iterator;
		//typedef bit::BRIterator<K,const const K&,const const K*> const_iterator;
		typedef typename bit::BRTree< K, const K, KeyOf>::const_self const_iterator;//这个要写typename,因为是在未实例化的模版里面用的变量
		typedef typename bit::BRTree< K, const K, KeyOf>::self iterator;
		void inorder()
		{
			_t.InOrder();
		}

		auto search(const K& k)
		{
			return _t.Search(k);
		}

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

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

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

		const_iterator begin()const
		{
			return _t.Begin();
		}

		const_iterator end()const
		{
			return _t.End();
		}

	private:
		BRTree< K,const K, KeyOf> _t;
	};

	void print(const set<int> s)
	{
		auto it = s.begin();
		while (it != s.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl;
	}

	void test_set()
	{
		set<int> s;
		s.insert(1);
		s.insert(9);
		s.insert(3);
		s.insert(4);
		s.insert(6);
		s.insert(2);
		s.insert(4);
		/*auto p = s.search(4);
		cout << p->_kv << endl;
		s.inorder();*/
		/*for (auto x : s)
		{
			cout << x << ' ';
		}
		cout << endl;
		auto it = s.begin();
		while (it != s.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl;
		it = s.end();
		while (it != s.begin())
		{
			--it;
			cout << *it << " ";
		}*/

		print(s);
	}
}

3.3 map.h

#pragma once

namespace bit
{
	template<class K,class V>
	class map
	{
	public:

		struct KeyOf
		{
			K operator()(const pair<const K, V>& kv)
			{
				return kv.first;
			}
		};

		//在这里也要写上const,因为k和v传过来,如果没写const,那么传进去,在传进去,里面的pair就是pair<K, V>,所以就很混乱
		typedef bit::BRIterator<pair<const K, V>, pair<const K, V>&, pair<const K, V>*> iterator;
		typedef bit::BRIterator<pair<const K, V>, const pair<const K, V>&,const pair<const K, V>*> const_iterator;

		//K KeyOf(const pair<K, V>& kv)//函数定义在后面,前面要是用的话就要提前声明,但是这里比较麻烦,因为有两个
		//{
		//	return kv.first;
		//}

		void inorder()
		{
			_t.InOrder();
		}

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

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

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

		const_iterator begin()const
		{
			return _t.Begin();
		}

		V& operator[](const K& key)
		{
			//要调用insert
			pair<iterator, bool> it=insert(make_pair(key, V()));//如果写pair的话就要说明类型,make_pair就不用说明类型了
			//it.first这个是迭代器,在解引用就会得到pair<K, V>,或者>
			return it.first->second;//
		}

		const_iterator end()const
		{
			return _t.End();
		}
	private:
		BRTree<const K, pair<const K, V>, KeyOf> _t;//搜索树是不能修改key的
	};

	void test_map()
	{
		map<string, string> m;
		m.insert(make_pair("eeeee", "aaaa"));
		m.insert({ "cccc","aaaa" });
		m.insert({ "aaaa","aaaa" });
		m.insert({ "ddddd","aaaa" });
		m.insert({ "aaaa","aaaa" });
		m["mmmmm"] = "mmmmmm";
		m["kkkkkkk"];
		m["mmmmm"] = "2222";
		m.inorder();
		for (auto x : m)
		{
			//x.first += 'a';
			cout << x.first << ' ';
		}
		cout << endl;
		auto it = m.begin();
		while (it != m.end())
		{
			cout << it->first << " " << it->second << endl;
			++it;
		}
		cout << endl;
		/*it = m.end();
		while (it != m.begin())
		{
			--it;
			cout << (*it).first << " ";
		}*/
	}
}

总结

下一篇我们讲哈希表

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值