嗯。。。总是忘。。。
再查以前做的笔记也好麻烦。。。于是将以前做的笔记重新整理、再整合其他优质内容,存到博客上吧,方便以后看。。。
红黑树是许多"平衡"搜索树的一种,可以保证在最坏情况下基本动态操作集合的时间复杂度为O(lgn);
1、红黑树的性质
以上节选自《算法导论<第三版>》;
首先可以看到,红黑树是一颗二叉搜索树,那就简单一提二叉搜索树,BST的特性:
某节点的左子树节点值仅包含小于该节点值;
某节点的右子树节点值仅包含大于该节点值;
左右子树每个也必须是二叉查找树;有一种情况,就是会形成"长腿",从程序的角度来说这个树不够平衡,查找次数或时间复杂度 O(h)可能会随着一条腿长无限增长;
红黑树其实就是去除二叉查找树顶端优势的解决方案,从而达到树的平衡(也就是,红黑树能够做到:最长路径不超过最短路径的二倍,因而近似平衡);
2、红黑树的插入
红黑树插入节点过程大致分析:
- RBTree为二叉搜索树,我们按照二叉搜索树的方法对其进行节点插入;
- RBTree有颜色约束性质,因此我们在插入新节点之后要进行颜色调整;
具体步骤如下:
- 根节点为NULL,直接插入新节点并将其颜色置为黑色
- 根节点不为NULL,找到要插入新节点的位置
- 插入新节点
- 判断新插入节点对全树颜色的影响,更新调整颜色
插入节点默认颜色一定要为红,如果为黑调节成本太大了;
红黑树有两大操作:
recolor (重新标记黑色或红色)
rotation (旋转,这是树达到平衡的关键)
先尝试 recolor,如果 recolor 不能达到红黑树的 性质要求,然后我们尝试 rotation,其实红黑树的关键玩法就是弄清楚 recolor 和 rotation 的规则。
算法公式:
假设,新插入节点为X,其父节点为P(若有),叔节点为U(若有),祖节点为G(若有);
公式一:
1.将新插入的节点标记为红色(新插入节点默认为红色);
2.如果 X 是根结点(root),则标记为黑色;
3.如果 X 的 parent 是红色(同时 X 也不是 root)、X 的 uncle (叔叔) 是红色,
将 parent 和 uncle 标记为黑色、将 grand parent (祖父) 标记为红色,
让 X 祖父的颜色与X 节点的颜色相同:红色,然后重复步骤 2、3;
公式二:
1.将新插入的节点标记为红色(新插入节点默认为红色);
2.如果 X 的 parent 是红色(同时 X 也不是 root)、如果 X 的 叔节点u是黑色(包括U不存在的情况),我们要分四种情况处理:
左左 (P 是 G 的左孩子,并且 X 是 P 的左孩子)
左右 (P 是 G 的左孩子,并且 X 是 P 的右孩子)
右右 (P 是 G 的右孩子,并且 X 是 P 的右孩子)
右左 (P 是 G 的右孩子,并且 X 是 P 的左孩子)
左左:右旋
左右:PX先左旋,这样就回到了"左左情况":再右旋
右右:左旋
右左:PX先右旋,这样就回到了"右右"情况:再左旋
参考:
知乎-老刘:红黑树,超强动静图详解,简单易懂:https://zhuanlan.zhihu.com/p/79980618?utm_source=cn.wiz.note
浅析红黑树(RBTree)原理及实现:https://blog.csdn.net/tanrui519521/article/details/80980135