红黑树的插入删除及迭代器的实现(c++实现)

红黑树是一种高效的搜索,查找数据结构,其被应用于c++STL容器的底层(vector等)

红黑树的性质:

1:每个节点不是红色就是黑色

2:根结点是黑色的

3:如果一个节点是红色的,则它的两个孩子节点是黑色的

4:对于每个节点,从该节点到其所有后代的简单路径上,均包含相同数目的黑色节点

5:每个叶子节点都是黑色的(这里的叶子节点指空结点)

大家想一想为什么凭借这几个性质就可以保证搜索效率呢?

因为性质三,红黑树不允许同时出现两个红色的节点,这就保证了在及其极端的情况下,红黑树也能保持高效的查找效率,这也是相比较AVL树的优点。

因为性质四,每条路径的的黑色节点数量都是一样的,这就说明树的权值最多为2倍;

实现:直接上代码,有注释

每次均插入一个节点,以红色插入,这样保证了及时的调整;注:图在最后面

#pragma once
#include<iostream>
#include<stack>
#include<utility>


namespace wr
{
	enum COLOR
	{
		BLACK,
		RED,
		EMPTY,
	};

	//红黑树每个节点的结构
	template<class T>
	class RBTreeNode
	{
		COLOR m_colour;
		T m_val;
		RBTreeNode<T> *m_left;
		RBTreeNode<T> *m_right;
		RBTreeNode<T> *m_parent;

	public:

		RBTreeNode(T val = T(), COLOR color = RED) :
			m_left(nullptr),
			m_right(nullptr),
			m_parent(nullptr),
			m_colour(color),
			m_val(val)
		{}

		bool operator==(RBTreeNode *right)
		{
			if (m_colour == right->m_colour &&
				m_val == right->m_val)
			{
				return true;
			}
			return false;
		}

		template<class T>
		friend class RBTree;

	};

	template<class T>
	class RBTree
	{
		RBTreeNode<T>* m_head;//头节点

	public:
		RBTree() :
			m_head(new RBTreeNode<T>(1, BLACK))
		{}

		//插入函数
		bool insert(T val)
		{
			RBTreeNode<T> *root = getRoot();

			if (root)
			{
				RBTreeNode<T>* pre = root;//记录当前节点的父节点
				RBTreeNode<T>* cur = root;//记录当前节点

				bool sign = true;//标记应该插在左子树还是右子树
				while (cur)//寻找插入的点
				{
					pre = cur;
					if (cur->m_val > val)
					{
						cur = cur->m_left;
						sign = true;
					}
					else if (cur->m_val < val)
					{
						cur = cur->m_right;
						sign = false;
					}
					else
					{
						return false;
					}
				}

				cur = new RBTreeNode<T>(val);//插入
				if (sign)
				{
					pre->m_left = cur;
				}
				else
				{
					pre->m_right = cur;
				}
				cur->m_parent = pre;

				//以下为红黑树调整算法
				if (pre->m_colour == RED)
				{
					RBTreeNode<T> *grand = nullptr;
					RBTreeNode<T> *uncle = nullptr;
					getgu(pre, uncle, grand);//获得叔叔和爷爷节点

					while (pre != m_head && uncle && uncle->m_colour == RED)//如果叔叔是红色的
					{
						pre->m_colour = BLACK;
						uncle->m_colour = BLACK;
						grand->m_colour = RED;

						cur = grand;
						pre = cur->m_parent;
						if (pre->m_colour == BLACK)
						{
							break;
						}
						getgu(pre, uncle, grand);
					}

					if (pre->m_colour == RED)
					{
						if (pre == grand->m_left)
						{
							if (cur == pre->m_left)
							{
								Rrotate(grand);
							}
							else
							{
								Lrotate(pre);
								swap(pre, cur);
								Rrotate(grand);
							}
						}
						else
						{
							if (cur == pre->m_right)
							{
								Lrotate(grand);
							}
							else
							{
								Rrotate(pre);
								swap(pre, cur);
								Lrotate(grand);
							}
						}
						pre->m_colour = BLACK;
						grand->m_colour = RED;
					}

				}

			}
			else
			{
				root = new RBTreeNode<T>(val, wr::BLACK);
				m_head->m_parent = root;
				root->m_parent = m_head;
			}
			m_head->m_parent->m_parent = m_head;
			m_head->m_parent->m_colour = BLACK;

			//更新左右标记
			updataBegin();
			updataEnd();

			return true;
		}

		//删除函数
		bool erase(T val)
		{
			std::pair<bool, iterator<T>>it = find(val);//找到删除的元素位置
			if (!it.first)
			{
				return false;
			}
			RBTreeNode<T> *grand = nullptr;
			RBTreeNode<T> *uncle = nullptr;
			RBTreeNode<T> *dad = it.second.m_data;
			getgu(dad, uncle, grand);//获得叔叔节点和爷爷节点(删除的节点是爸爸)



			//删除操作
			if (dad->m_colour == BLACK)
			{
				if (dad->m_left == nullptr || dad->m_right == nullptr)
				{
					if (dad->m_left != nullptr)
					{
						if (grand->m_left == dad)
						{
							grand->m_left = dad->m_left;
						}
						else
						{
							grand->m_right = dad->m_left;
						}
						dad->m_left->m_parent = grand;
					}
					else if (dad->m_right != nullptr)
					{
						if (grand->m_left == dad)
						{
							grand->m_left = dad->m_right;
						}
						else
						{
							grand->m_right = dad->m_right;
						}
						dad->m_right->m_parent = grand;
					}
					else
					{
						if (grand->m_left == dad)
						{
							grand->m_left = nullptr;
						}
						else
						{
							grand->m_right = nullptr;
						}
					}

					delete dad;
					dad = nullptr;
					LockBlackNode(grand);//缺黑调整
				}
				//需要找到代替的点
				else
				{
					//首先我们需找到代替的节点
					++it.second;
					RBTreeNode<T> *areplace = it.second.m_data;//后继节点
					--it.second;
					--it.second;
					RBTreeNode<T> *preplace = it.second.m_data;//前驱节点

					if (areplace->m_colour == RED || preplace->m_colour == RED)//如果被替代的是红色的,直接替换
					{
						if (areplace->m_colour == RED)
						{
							dad->m_val = areplace->m_val;
							if (areplace == dad->m_left)//如果后继不是被删除节点的左子树,那么它一定是某个节点的左子树
							{
								dad->m_left = nullptr;
							}
							else
							{
								areplace->m_parent->m_left = nullptr;
							}
						}
						else
						{
							dad->m_val = preplace->m_val;
							if (preplace == dad->m_left)//如果前驱节点不是被删除节点的右子树,那么它一定是某个节点的右子树
							{
								dad->m_right = nullptr;
							}
							else
							{
								preplace->m_parent->m_right = nullptr;
							}
						}
					}
					//如果前驱节点和后继节点都是黑色,则进行黑色调整
					else
					{
						//替换
						dad->m_val = areplace->m_val;
						RBTreeNode<T>*parent = areplace->m_parent;//记录被替换节点的路径
						if (areplace == dad->m_left)//如果后继不是被删除节点的左子树,那么它一定是某个节点的左子树
						{
							dad->m_left = nullptr;
						}
						else
						{
							areplace->m_parent->m_left = nullptr;
						}
						//缺黑调整
						LockBlackNode(parent);
					}
			
				}

			}
			else
			{
				//如果被删除节点的左右节点有1/2个子节点为nullptr,直接删除
				if (dad->m_left == nullptr || dad->m_right == nullptr)
				{
					if (grand->m_left == dad)
					{
						if (dad->m_left == nullptr)
						{
							grand->m_left = dad->m_right;
						}
						else
						{
							grand->m_left = dad->m_left;
						}
					}
					else
					{
						if (dad->m_left == nullptr)
						{
							grand->m_right = dad->m_right;
						}
						else
						{
							grand->m_right = dad->m_left;
						}
					}
				}
				//需要找到替换的节点
				else
				{
					//首先我们需找到代替的节点
					++it.second;
					RBTreeNode<T> *areplace = it.second.m_data;//后继节点
					--it.second;
					--it.second;
					RBTreeNode<T> *preplace = it.second.m_data;//前驱节点

					if (areplace->m_colour == RED || preplace->m_colour == RED)//如果被替代的是红色的,直接替换
					{
						if (areplace->m_colour == RED)
						{
							dad->m_val = areplace->m_val;
							if (areplace == dad->m_left)//如果后继不是被删除节点的左子树,那么它一定是某个节点的左子树
							{
								dad->m_left = nullptr;
							}
							else
							{
								areplace->m_parent->m_left = nullptr;
							}
						}
						else
						{
							dad->m_val = preplace->m_val;
							if (preplace == dad->m_left)//如果前驱节点不是被删除节点的右子树,那么它一定是某个节点的右子树
							{
								dad->m_right = nullptr;
							}
							else
							{
								preplace->m_parent->m_right = nullptr;
							}
						}
					}
					//如果前驱节点和后继节点都是黑色,则进行黑色调整
					else
					{
						//替换
						dad->m_val = areplace->m_val;
						RBTreeNode<T>*parent = areplace->m_parent;//记录被替换节点的路径
						if (areplace == dad->m_left)//如果后继不是被删除节点的左子树,那么它一定是某个节点的左子树
						{
							dad->m_left = nullptr;
						}
						else
						{
							areplace->m_parent->m_left = nullptr;
						}
						//缺黑调整
						LockBlackNode(parent);
					}
				}
			}
			return true;
		}

		//缺黑调整
		void LockBlackNode(RBTreeNode<T> *path)
		{
			RBTreeNode<T>* cur = path;
			RBTreeNode<T>* pre = path;
			RBTreeNode<T>* tmp = path;

			//因为这条路径缺少了一个黑色节点,所以需要将其他路径均缺少一个节点
			//我们在这里寻找他这条路径上的所有子树,将这些子树的一个黑色节点染成红色。
			bool index = true;
			while (cur != m_head)
			{
				if (cur->m_left && cur->m_left != pre)//如果这条路径存在左子树,则将其左子树的一个黑色节点变红
				{
					//寻找其左子树的黑色节点,并将其变红
					index = ChangeColor(cur->m_left);
				}
				else if(cur->m_right && cur->m_right != pre)//如果这条路径存在右子树,则将其右子树的一个黑色节点变红
				{
					//寻找其右子树的黑色节点,并将其变红
					index = ChangeColor(cur->m_right);
				}
				if (!index)
				{
					break;
				}
				cur = pre;//cur的更新存在问题
				cur = cur->m_parent;
			}
			m_head->m_parent->m_colour = BLACK;
		}

		//寻找黑色节点,然后调用调整函数
		bool ChangeColor(RBTreeNode<T> *cur)
		{
			bool index = true;
			if (cur->m_colour == BLACK)
			{
				//找到了黑色节点,进行调整
				cur->m_colour = RED;
				bool index = AdjustColor(cur);
				if (!index)
				{
					return false;
				}
				return true;;
			}
			else
			{
				if (cur->m_left)
				{
					bool index = ChangeColor(cur->m_left);
				}
				if (cur->m_right)
				{
					bool index = ChangeColor(cur->m_right);
				}
			}
			return index;
		}

		bool AdjustColor(RBTreeNode<T> *cur)
		{
			//找到其左右节点的颜色
			COLOR leftcolor = BLACK;
			COLOR rightcolor = BLACK;
			if (cur->m_left && cur->m_left->m_colour == RED)
			{
				leftcolor = RED;
			}
			if (cur->m_right &&cur->m_right->m_colour == RED)
			{
				rightcolor = RED;
			}

			//如果父亲节点为黑色
			if (cur->m_parent->m_colour == BLACK)
			{
				if (leftcolor == BLACK && rightcolor == BLACK)
				{
					//方法一
					Bbb(cur);
				}
				else if (leftcolor == RED && rightcolor == RED)
				{
					//方法二
					Brr(cur);
				}
				else
				{
					Brb(cur);//方法三
				}
			}
			else
			{
				if (leftcolor == BLACK && rightcolor == BLACK)
				{
					Rbb(cur);//方法四
					return false;
				}
				else if (leftcolor == RED && rightcolor == RED)
				{
					Rrr(cur);//方法五
				}
				else
				{
					Rrb(cur);//方法六
				}
			}
			return true;
		}

		//六种处理函数
		void Bbb(RBTreeNode<T> *cur)
		{}
		void Brr(RBTreeNode<T> *cur)
		{
			if (cur->m_parent->m_left == cur)
			{
				Lrotate(cur);
				cur = cur->m_parent;
				Rrotate(cur->m_parent);
				cur->m_left->m_colour = BLACK;
			}
			else
			{
				Rrotate(cur);
				cur = cur->m_parent;
				Lrotate(cur->m_parent);
				cur->m_right->m_colour= BLACK;
			}
			if (cur->m_parent != m_head && cur->m_parent->m_colour == RED)
			{
				Rbb(cur);
			}
		}
		void Brb(RBTreeNode<T> *cur)
		{
			if (cur->m_parent->m_left = cur)
			{
				Lrotate(cur);
				cur = cur->m_parent;
				Rrotate(cur->m_parent);
				cur->m_left->m_colour = BLACK;
			}
			else
			{
				Rrotate(cur);
				cur = cur->m_parent;
				Lrotate(cur->m_parent);
				cur->m_right->m_colour = BLACK;
			}
			if (cur->m_parent != m_head && cur->m_parent->m_colour == RED)
			{
				Rbb(cur);
			}
		}
		void Rbb(RBTreeNode<T> *cur)//若执行了之一步可以直接退出
		{
			cur->m_parent->m_colour = BLACK;
		}
		void Rrr(RBTreeNode<T> *cur)
		{
			cur->m_parent->m_colour = BLACK;
			Brr(cur);
		}
		void Rrb(RBTreeNode<T> *cur)
		{
			COLOR leftcolor = BLACK;
			COLOR rightcolor = BLACK;
			if (cur->m_left && cur->m_left->m_colour == RED)
			{
				leftcolor = RED;
			}
			if (cur->m_right &&cur->m_right->m_colour == RED)
			{
				rightcolor = RED;
			}

			if (cur = cur->m_parent->m_left)
			{
				if (rightcolor == RED)
				{
					Lrotate(cur);
					cur = cur->m_parent;
				}
				Rrotate(cur->m_parent);
				Brr(cur);
			}
			else
			{
				if (leftcolor == RED)
				{
					Rrotate(cur);
					cur = cur->m_parent;
				}
				Lrotate(cur->m_parent);
				Brr(cur);
			}
		}

		//以下是迭代器模块,使用内部类实现迭代器
		template<class T>
		class iterator
		{
		public:

			RBTreeNode<T> *m_data;
			RBTreeNode<T> *m_ithead;
			T m_max;

			iterator(RBTreeNode<T> *data, RBTreeNode<T> *ithead):
				m_data(data),
				m_max(data->m_val),
				m_ithead(ithead)
			{}

			iterator(const iterator&it)://拷贝构造
				m_data(it.m_data),
				m_ithead(it.m_ithead),
				m_max(it.m_max)
			{}

			T& operator*()
			{
				return m_data->m_val;
			}

			T* operator->()
			{
				return &m_data->m_val;
			}

			iterator<T> operator++()//使用中序从小到大的结论进行++,每次记录遍历过的最大值
			{
				if (m_data->m_colour == RED)
				{
					std::cout << "RED:";
				}
				else
				{
					std::cout << "BLACK:";
				}
				if (m_data == m_ithead->m_right)
				{
					m_data = m_ithead;
					return *this;
				}
				if (m_data->m_right && m_data->m_right->m_val > m_max)
				{
					m_data = m_data->m_right;
					while (m_data->m_left)
					{
						m_data = m_data->m_left;
					}
					m_max = m_data->m_val;
					return *this;
				}
				while(m_data->m_parent != m_ithead && m_data->m_val <= m_max)
				{
					m_data = m_data->m_parent;
				}
				m_max = m_data->m_val;
				return *this;
			}

			iterator<T> operator++(int)
			{
				iterator<T> tmp(*this);
				++(*this);
				return tmp;
			}

			iterator<T> operator--()
			{

				if (m_data == m_ithead->m_left)
				{
					std::cout << "cross boundary" << std::endl;
					return *this;
				}
				if (m_data->m_left && m_data->m_left->m_val < m_max)
				{
					m_data = m_data->m_left;
					while (m_data->m_right)
					{
						m_data = m_data->m_right;
					}
					m_max = m_data->m_val;
					return *this;
				}
				while (m_data->m_parent != m_ithead && m_data->m_val >= m_max)
				{
					m_data = m_data->m_parent;
				}
				m_max = m_data->m_val;
				return *this;
			}

			iterator<T> operator--(int)
			{
				iterator<T> tmp(*this);
				--(*this);
				return tmp;
			}

			bool operator==(iterator<T> &right)
			{
				return m_data->m_val == right.m_data->m_val;
			}

			bool operator!=(iterator<T> &right)
			{
				return !(*this == right);
			}

			bool operator<(iterator<T> &right)
			{
				return m_data->m_val < right.m_data->m_val;
			}

			bool operator>(iterator<T> &right)
			{
				return m_data->m_val > right->m_data->m_val;
			}

			T getval()
			{
				return m_data->m_val;
			}

		};
		
		//查找
		std::pair<bool,iterator<T>> find(T val)
		{
			iterator<T> it(m_head->m_left, m_head);
			while (it.m_data != m_head->m_right)
			{
				if (it.getval() == val)
				{
					return std::make_pair(true, it);
				}
				++it;
			}
			return std::make_pair(false, it);
		}

		iterator<T> begin()
		{
			return iterator<T>(m_head->m_left, m_head);
		}

		iterator<T> end()
		{
			return iterator<T>(m_head, m_head);
		}

	private:

		//获得叔叔节点和爷爷节点
		void getgu(wr::RBTreeNode<T> *pre, wr::RBTreeNode<T> *&uncle, wr::RBTreeNode<T> *&grand)
		{
			grand = pre->m_parent;
			if (pre == grand->m_left)
			{
				uncle = grand->m_right;
			}
			else
			{
				uncle = grand->m_left;
			}
		}

		//右旋函数
		void Rrotate(RBTreeNode<T> *root)
		{
			RBTreeNode<T> *grand = root->m_parent;
			RBTreeNode<T> *sun = root->m_left;
			if (grand != m_head)
			{
				if (grand->m_left == root)
				{
					grand->m_left = sun;
				}
				else
				{
					grand->m_right = sun;
				}
			}
			else
			{
				grand->m_parent = sun;
			}
			sun->m_parent = grand;
			if (sun->m_right)
			{
				root->m_left = sun->m_right;
				sun->m_right->m_parent = root;
			}
			else
			{
				root->m_left = nullptr;
			}
			sun->m_right = root;
			root->m_parent = sun;
		}

		//左旋函数
		void Lrotate(wr::RBTreeNode<T> *root)
		{
			RBTreeNode<T> *grand = root->m_parent;
			RBTreeNode<T> *sun = root->m_right;
			if (grand != m_head)
			{
				if (grand->m_left == root)
				{
					grand->m_left = sun;
				}
				else
				{
					grand->m_right = sun;
				}
			}
			else
			{
				grand->m_parent = sun;
			}
			sun->m_parent = grand;
			if (sun->m_left)
			{
				root->m_right = sun->m_left;
				sun->m_left->m_parent = root;
			}
			else
			{
				root->m_right = nullptr;
			}
			sun->m_left = root;
			root->m_parent = sun;
		}

		//交换
		void swap(wr::RBTreeNode<T> *&left, wr::RBTreeNode<T> *&right)
		{
			RBTreeNode<T> *tmp = left;
			left = right;
			right = tmp;
		}

		//获取头头节点
		RBTreeNode<T>* getRoot()
		{
			return m_head->m_parent;
		}

		//更新begin
		void updataBegin()
		{
			RBTreeNode<T> *tmp = m_head->m_left;
			if (nullptr == m_head->m_left)
			{
				tmp = m_head->m_parent;
				while (tmp)
				{
					m_head->m_left = tmp;
					tmp = tmp->m_left;
				}
			}
			else
			{
				while (tmp->m_left)
				{
					tmp = tmp->m_left;
				}
				m_head->m_left = tmp;
			}
		}

		//更新end
		void updataEnd()
		{
			RBTreeNode<T> *tmp = m_head->m_right;
			if (nullptr == m_head->m_right)
			{
				tmp = m_head->m_parent;
				while (tmp)
				{
					m_head->m_right = tmp;
					tmp = tmp->m_right;
				}
			}
			else
			{
				while (tmp->m_right)
				{
					tmp = tmp->m_right; 
				}
				m_head->m_right = tmp;
			}
		}

	};

}

最后送大家一张图,帮助对插入的理解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值