C++红黑树的插入实现+红黑树迭代器实现+map/set封装红黑树

目录

红黑树的基本编写

红黑树的概念

红黑树的性质

红黑树节点的定义

红黑树的插入操作

情况1.1

情况2

情况3:

判断平衡

测试

用红黑树封装map和set

迭代器

【operator++】

operator--

operator!=

map和set封装迭代器

find迭代器查找

对红黑树中Insert的改变

拷贝构造问题

赋值重载


红黑树的基本编写

红黑树的概念

红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的

红黑树的性质

  1. 每个节点不是红色就是黑色
  2. 根节点是黑色的
  3. 没有连续的红色节点,但是可以有连续的黑色节点
  4. 每条路径黑色节点数量相等
  5. 每个叶子节点都是黑色的(此处的叶子节点值得是空节点--NIL节点,不是以前真正意义上理解的叶子节点)。

假设每条路径的黑节点数量是N,由此可以得知:任意路径长度>=N && 任意路径长度<=2N,这就说明虽短路径是全黑的,最长路径是一黑一红,这也证明最长路径不超过最短路径的2倍

所以AVL树严格平衡,效率是logN(以2为底),红黑树是近似平衡,效率是2*logN。虽然红黑树效率没有AVL树高,但是对于现阶段的计算机而言,这点效率已经可以忽略不记。并且AVL树在达到平衡的目的下,需要进行旋转,而红黑树没有到最短路径2倍是不用旋转的,AVL树的旋转次数多,使效率降低,所以更推荐用红黑树。

红黑树节点的定义

红黑树的颜色我们用枚举定义,节点的定义用一个三叉链,构造节点,随便给一个颜色,

enum Color
{
	RED,
	BLACK
};

template<class K,class V>
struct RBTreeNode
{
	RBTreeNode<K, V>* _left;
	RBTreeNode<K, V>* _right;
	RBTreeNode<K, V>* _parent;
	Color _col;
	pair<K, V> _kv;

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

红黑树的插入操作

红黑树也是一个二叉搜索树,所以插入值的时候,如果值存在返回false,如果不存在,比当前节点大就向右边插入,如果比当前节点值小,向左边插入。

红黑树右两种颜色,红和黑。对于插入操作,我们因该插入哪个颜色的节点呢?如果插入黑色,那么这条路径的黑色节点数量就会改变,使得每条路径都要增加黑色节点,代价太大了,所以我们选择插入红色节点。

【插入红色节点分以下几种情况】:

约定:cur为当前节点,g为祖父节点,u为叔叔节点

情况1.1

:cur是新增为红,parent为红,grandfather为黑,uncle叔叔节点存在且为红。前三条是固定条件,唯一要看的就是uncle的情况。

解决方式:将p,u改为黑,g改为红,然后把g当cur,继续向上调整

因为新增了红,且有两个连续红节点,所以要向上更新parent节点的颜色为黑,uncle节点也要变成黑色。因为grandparent的节点不一定是根节点,如果不是根节点,需要将grandparent的节点颜色变成红色,来保证每条路径的黑色节点数量相同。当grandparent节点变成红色后,可能又会出现两个连续的红色节点,那么就衍生出第二种情况。

情况1.2:cur不是新增红色节点,parent为红,grandfather为黑,uncle叔叔节点存在且为红。

这种情况和情况1类似,只是cur不是新增节点,而是本就存在的节点。它最开始是有图1变换而来的,最后还是通过情况1的解决方法,也就是将情况1的grandparent当成cur,将现在的parent和uncle节点变黑,grandparent节点变红。如果g节点是根节点,就再次变黑。只要uncle存在且parent和uncle都为红,就会一直这样处理

情况2

:uncle不存在 || uncle存在且为黑

解决方案:parent为grandfather的左孩子,cur为p的左孩子,则进行右单旋;相反,如果parent为grandfather的右孩子,cur为parent的右孩子,则进行左单旋。parent和grandfather变色:parent变黑,grandfater变红。

uncle不存在的情况下,如上图,如果没有uncle,那么只有一个黑节点,并且增加一个新的节点cur后,左树的路径长度超过了右树路径长度的2倍(从grandfather节点算起)。那么此时不单纯是改变节点颜色的问题,在AVL树中,左右子树高度差大于2,会进行旋转操作。

红黑树中,uncle节点不存在或者为黑的情况,会进行

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值