C++从零开始(day50)——RBTree模拟实现

这是关于一个普通双非本科大一学生的C++的学习记录贴

在此前,我学了一点点C语言还有简单的数据结构,如果有小伙伴想和我一起学习的,可以私信我交流分享学习资料

那么开启正题

今天分享的是关于RBTree模拟实现

1.RBTree概念

RBTree(红黑树),是一种二叉搜索树,在每个结点增加一个存储标识结点颜色,可以是RED或者BLACK(因而得名),通过对任意一条叶子路径上的各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,因而使近似平衡

2.RBTree的性质

1.根节点是黑色的 

2.没有相邻的红结点

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

4. 每个空结点都是黑色的

3.RBTree结点的定义

RBTree结点是一种三岔链,不仅存储了左右子树结点的指针,还要存储父亲结点的指针,当然还要存储结点颜色以及pair

enum Colour
{
	BLACK,
	RED
};

template<class K, class V>
struct RBTreeNode
{
	RBTreeNode<K, V>* _left;
	RBTreeNode<K, V>* _right;
	RBTreeNode<K, V>* _parent;

	pair<K, V> _kv;
	Colour _col;

	RBTreeNode(const pair<K, V>& kv)
		:_left(nullptr)
		, _right(nullptr)
		, _parent(nullptr)
		, _col(RED)
		, _kv(kv)
	{}
};

4.RBLTree的插入

4.1插入流程

RBTree树插入数据可以分为两步

1.按照二叉搜索树的方式插入新结点

2.调整结点的颜色

在调节颜色时,有时需要旋转处理,旋转方式和我们刚学的AVLTree旋转方式一样

4.2插入情况

先按照二叉搜索树进行插入,当然注意颜色的处理

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;
		cur->_parent = parent;
	}
	else
	{
		parent->_left = cur;
		cur->_parent = parent;
	}


    //。。。。。    

	_root->_col = BLACK;

	return true;
}

4.2.1叔叔为红色

当叔叔为红色时,把叔叔父亲变为黑,祖父变为红,往上继续迭代即可

4.2.1叔叔为黑色或不存在

当叔叔叔叔为黑色或不存在时,要进行旋转,旋转完成调色后,退出循环

while (parent && parent->_col == RED)
{
	Node* grandfater = parent->_parent;
	if (parent == grandfater->_left)
	{
		Node* uncle = grandfater->_right;
		// 情况一  uncle存在且为红
		if (uncle && uncle->_col == RED)
		{
			parent->_col = uncle->_col = BLACK;
			grandfater->_col = RED;

			cur = grandfater;
			parent = cur->_parent;
		}
		else
		{
			if (cur == parent->_left)
			{
				// 情况二
				RotateR(grandfater);
				parent->_col = BLACK;
				grandfater->_col = RED;
			}
			else
			{
				// 情况三
				RotateL(parent);
				RotateR(grandfater);
				cur->_col = BLACK;
				grandfater->_col = RED;
			}

			break;
		}
	}
	else // (parent == grandfater->_right)
	{
		Node* uncle = grandfater->_left;
		if (uncle && uncle->_col == RED)
		{
			parent->_col = uncle->_col = BLACK;
			grandfater->_col = RED;

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

			break;
		}
	}
}

注意::完成后,根可能为红色(违反红黑树性质),要处理为黑色

当然红黑树还有其他函数,以及迭代器,这些在后面模拟实现map和set里再深入探究

新手写博客,有不对的位置希望大佬们能够指出,也谢谢大家能看到这里,让我们一起学习进步吧!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值