红黑树的插入

红黑树的插入总共不算镜像的话总共五种情况:

  1. 插入就要做根,即插入之前树中没有结点,插入的这个结点就是m_head的parent
  2. 第二种就是插入的父亲是黑的,所以不需要改变
  3. 第三种就是插入的父亲是红的,叔叔也是红的,此时需要的操作是改色,将父亲结点与叔叔结点的颜色变成黑的,将爷爷结点的颜色变成红色,然后继续向上遍历,将所有的出现的这种情况都处理了,如果遇到根就先变红再变黑,即遇到m_head就退出
  4. 第四种是父亲是红色,但是叔叔是黑的,我和父亲一条线,进行单旋,单旋结束后将父亲的额颜色变成黑色,爷爷的颜色变成红色
  5. 最后一种如果我父亲是红色,叔叔黑色,但是我和父亲不在一条线上没救需要根据情况进行双旋,第一次旋转之后交换一下我和父亲结点,然后就和第四种一样了,最后记得将爷爷变红,父亲变黑
bool insert(const T & val)
	{
		RBTreeNode<T> * & root = getRoot();

		if (root)
		{
			RBTreeNode<T> * cur = root;
			RBTreeNode<T> * pre = nullptr;

			while (cur)
			{
				if (val < cur->m_data)
				{
					pre = cur;
					cur = cur->m_left;
				}
				else if (val > cur->m_data)
				{
					pre = cur;
					cur = cur->m_right;
				}
				else
				{
					return false;
				}
			}
			//上面的代码完成的是查找要插入的点的位置
			
			cur = new RBTreeNode<T>(val);
			if (val < pre->m_data)
			{
				pre->m_left = cur;
			}
			else
			{
				pre->m_right = cur;
			}

			cur->m_parent = pre;
			//上面的代码完成的是将要插入的点在pre的左边还是右边确定下来

			if (pre->m_color == RED)
			{
				RBTreeNode<T> * grand = pre->m_parent;
				RBTreeNode<T> * uncle;

				if (pre == grand->m_left)
				{
					while (pre != m_head && pre->m_color == RED)
					{
						grand = pre->m_parent;
						uncle = grand->m_right;

						if (uncle && uncle->m_color == RED)//第三种情况
						{
							pre->m_color = BLACK;
							uncle->m_color = BLACK;
							grand->m_color = RED;

							cur = grand;
							pre = cur->m_parent;
						}
						else
						{
							if (cur == pre->m_right)
							{
								lRound(pre);
								RBTreeNode<T> * tmp;
								tmp = pre;
								pre = cur;
								cur = tmp;
							}

							rRound(grand);
							pre->m_color = BLACK;
							grand->m_color = RED;
							break;
						}
					}
				}
				else
				{
					while (pre != m_head && pre->m_color == RED)
					{
						grand = pre->m_parent;
						uncle = grand->m_left;

						if (uncle && uncle->m_color == RED)//第三种情况
						{
							pre->m_color = BLACK;
							uncle->m_color = BLACK;
							grand->m_color = RED;

							cur = grand;
							pre = cur->m_parent;
						}
						else
						{
							if (cur == pre->m_left)
							{
								rRound(pre);
								RBTreeNode<T> * tmp;
								tmp = pre;
								pre = cur;
								cur = tmp;
							}

							lRound(grand);
							pre->m_color = BLACK;
							grand->m_color = RED;
							break;
						}
					}
				}
			}
			//省略的else是第二种情况
		}
		else//第一种情况
		{
			root = new RBTreeNode<T>(val, BLACK);
			root->m_parent = m_head;
			m_head->m_parent = root;
		}

		root->m_color = BLACK;
		m_head->m_left = leftMost();
		m_head->m_right = rightMost();
		return true;
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值