红黑树、B树、234树
一、红黑树
特性:1.每个节点是黑色或者红色的
2.根节点是黑色的
3.每个叶节点(NIL)是黑色的
4.不能有相连的红色节点
5.对每个节点,从该节点到其所有叶节点的路径上,均包含相同数量的黑色节点。
红黑树插入:
详细插入:
接上
插入总结:
1.插入红节点(如果黑节点就会出现链表情况,不违反红黑树的特性)
2.待插入节点z与父节点p冲突。
2.1 叔节点u为红色。则需将爷爷节点pp变红,p和u变红。且将pp标记为新的z
2.2 u为黑色。则需要旋转(以z的父节点为轴旋转)。并将父节点p标记为新的z
3.一次以p的旋转必然伴随着一次以pp的旋转。(当z与p与pp同一条线即同一侧,则直接以pp旋转一次即可)
4.循环的修复红黑树的特性,目标是修复到z.p.color为黑色的时候退出循环
红黑树删除(比较复杂,引入算法导论中伪代码与图形):
1.位置替换伪代码:
/*** 只是处理了u.p的指针指向。在外部还需手动处理v的子类指针**/
RB-TRANSPLANT(T, u, v) {if(u.p == T.nil) {T.root = v}else if (u == u.p.left) {u.p.left = v}else u.p.right = vv.p = u.p
}
2. 删除伪代码:
RB-DELETE(T, z) {y = zy-original-color = y.colorif (z.left == T.nil) {x = z.rightRB-TRANSPLANT(T, z, z.right)} else if (z.right == T.nil) {x = z.leftRB-TRANSPLANT(T, z, z.left);} else {y = TREE-MINIMUM(z.right) // z的后继节点y-original-color = y.colorx = y.rightif (y.p == z) { // y为z的右子节点,且是后继节点x.p = y// z被y替换时。y的右节点不需要处理。左节点需要自处理}else {RB-TRANSPLANT(T, y, y.right) // 为z被y替换处理,子节点需要自处理。左右节点都需要处理y.right = z.right y.right.p = y} RB-TRANSPLANT(T, z, y)// z被y替换之后,子节点的自处理。此处只需要处理左节点y.left = z.lefty.left.p = yy.color = z.color // 将y置为z的color.最终影响树性质的,决定权在y的原始颜色,y-original-color}// z只存在一个子节点的时候。y==z。y == z.color.影响树的性质,依然由y-original-color控制if (y-original-color == BLACK) {RB-DELETE-FIXUP(T, x)}}
3.删除-红黑树性质修复伪代码:
y的原始颜色y-original-color==RED时。
1.黑高不会变换。
2.y一定不是根节点,所以根节点依然是黑色
3.y只存在一个子节点的时候,y == z 。z被y的唯一子节点代替,无任何改变红黑树性质的可能。
4.y存在两个子节点,且y为z的右子节点时,即y也是z的后继节点。后继节点必然为其右子树中最小的,且y不存在左节点了。y为红色则y.right一定为黑色。y.right替换掉y之后红黑树性质也不可能冲突。
y的原始颜色y-original-color==BLACK时。
1.y为根节点,则其子节点替换,根节点就变红色,则违反了性质2。
2.删除之后,x与x.p(删除之前y.p)都为红色。则违反了性质4
3.将包含y的任一子树的黑节点个数都少一。因此y的任何祖先都补满足性质5。针对这一情况,算法导论中的处理方式为:将y的黑色下方到x,x为红色(自身黑属性+下方红),黑色(自身黑属性+下方黑色),x多出来的黑色并不是体现在x的color属性上,而是针对的x节点。包含x的子树中,x共享了一重黑色,或则两重黑色,从而保证了性质5。但是x却违反了性质1。
RB-DELETE-FIXUP:
RB-DELETE-FIXUP(T, x) {while (x != T.root && x.color == BLACK) {// x作为左节点if (x == x.p.left) {// x的兄弟节点ww = x.p.right// 情况1:x的兄弟结点w为红色,x.p.color必然为黑色。// 为保证红黑树的特性,可以将x.p与w的颜色改变// 接着以x.p为轴左转,并不会影响特性。就变成情况2,3,4if (w.color == RED) {w.color = BLACKx.p.color = REDLEFT-ROTATE(T, x.p)w = x.p.right}// 经过情况1的过滤:2,3,4的w必然是为黑色的// 情况2:w黑色,w的两个子节点都是黑色的// 将x上移至x.p,则w子树就会随着x多了一层黑,则需将w变红if (w.left.color == BLACK && w.right.color == BLACK) {x = x.p // 如果是情况1过来的,则此时x为红黑色,x.color = RED。所以得退出循环,并将x.color = BLACKw.color = RED} // 情况3:w黑色, w左孩子红色,w的有孩子为黑色// 交换w.left和w的颜色,并以w向右旋转。则特性不会变。并将w置为x.p.right.// 情况3就变为情况4了else if (w.right.color == BLACK) {w.left.color = BLACKw.color = REDRIGHT-ROTATE(T, w)w = x.p.right}// 情况4:w黑色,w的右孩子是红色的// 将x.p、w、w.right的颜色变换,并以x.p为轴向左旋转,即可保证特性,也可顺带去掉x的多一层黑色。else {// w与x.p的颜色交换// 以x.p为轴旋转,则w子树必然少一个黑,所以将w.right置黑。// 而x所在子树因转来个x.p的黑节点,则多一黑,刚好x的颜色多了黑直接去掉// x置为root 退出循环。w.color = x.p.color x.p.color = BLACK w.right.color = BLACKLEFT-ROTATE(T, x.p)x = T.root}}}x.color = BLACK
}
4.删除-图形示例:
总结:红黑树删除,需要找到后继节点y(可能为z的右节点,也有可能非右节点的后继)。
1. 红黑树增加维持红黑树的特性是看其叔叔,删除是看其兄弟节点控制x和w的移动变换,以及旋转和相关的变色。
2. 循环的修复红黑树特性,情况2由情况1过来,导致x.color=red只是作为x多了一层额外的黑色,从而退出循环。还有就是目的性的调整到x的兄弟节点为黑色,且w.right=red即情况4,很容易将原x的子树增加1曾黑色且将x置为root退出循环。
二、B树
一个B树结点通常和一个完整磁盘页一样大,并且磁盘页的大小限制了一个B树结点可以含有的孩子的个数。一个典型的磁盘的长度,可能为2^11~2^14字节。
度:每个结点包含的关键字个数有上界和下界。用一个被称为B树的最小度数degree的固定整数t>=2来表示这些界。
a.除了根结点以外的每个结点必须至少有t-1个关键字。因此除了根结点之外的每个内部结点至少有t个孩子。如果树非空,根结点至少有一个关键字。
b.每个结点至多可包含2t-1个关键字。因此一个内部结点至多有2t个孩子。当一个结点恰好有2t-1个关键字,则称该结点是满的full。
t =< 内部结点数 <= 2t
阶:对于一个m阶B树,根结点的子结点个数为1~m,非根结点的子关键字个数为[m/2]-1~m-1。子结点个数为[m/2]~m.因为当前节点满了之后,继续添加关键字。必然分裂成两半也就是[m/2]-1个关键字,[m/2]个子结点。
[m/ 2]=< 内部结点数 <= m
·综上:m = 2d。
1. B数的插入
伪代码就不贴上了
总结:插入是预分裂。确保到任何叶结点可以直接插入。
插入叶结点,未full(关键字数 = 2d - 1)直接插入。当叶子结点full则需要按中间值分裂。并上移中间关键字。插入的过程中如果发现,遍历的过程中,有full的结点,则提前分裂,分裂好之后再接着遍历插入。
2. B树的删除
总结:删除是预合并,或者预向兄弟结点借用。
1. 被删除节点x的关键字必须满足(t~2t-1).满足条件的叶结点直接删除。
2. x为内部结点,且满足至少t个关键字。则需找k的前驱prev或者后继suc。
ab.如果prev和suc至少有一个满足至少t个关键字,则找到k的前驱k1或者后继(递归下去)。使用k1代替k。
c.prev和suc都不满足至少一个关键字t,皆是t-1个下限关键字。则将k下移至prev且将suc合并至prev并将suc中的孩子指针移动到prev。
3. 从根节点遍历下移的过程中,遇到t-1个的关键字x。
a.找到x的相邻的两个兄弟结点,如果有满足至少t个关键字的b结点。则将b中的关键字上移至父节点(注意递归),并将父节点中的关键字下移至x。并将b中的孩子子指针移入x。
b.找不到满足条件的兄弟结点,则将父节点关键字下移,且将兄弟结点b合并到x。且
b的孩子指针移入x。
三.234树
234树为度数为2的B树。也可与红黑树相互转换.
红黑树、B树、234树相关推荐
- 为什么HashMap使用红黑树而不使用AVL树
在Jdk1.8版本后,Java对HashMap做了改进,在链表长度大于8的时候,将后面的数据存在红黑树中,以加快检索速度. 那么很多人就有疑问为什么是使用红黑树而不是AVL树,AVL树是完全平衡二叉树 ...
- 遍历HashMap源码——红黑树原理、HashMap红黑树实现与反树型化(三)
本章将是HashMap源码的最后一章,将介绍红黑树及其实现,HashMap的remove方法与反树型化.长文预警~~ 遍历HashMap源码--红黑树原理.HashMap红黑树实现与反树型化 什么是红 ...
- 面试题:为什么用红黑树不用普通的AVL树
在Jdk1.8版本后,Java对HashMap做了改进,在链表长度大于8的时候,将后面的数据由链表改为了存在红黑树中,以加快检索速度. 有疑问为什么是使用红黑树而不是AVL树,AVL树是完全平衡二叉树 ...
- 2-3树------2-3-4树-----左倾红黑树
2-3树: 2-节点:含有一个键和两条链接,左链接指向的2-3树中的键都小于该节点,右链接指向的2-3树中的键都大于该节点. 3-节点:含有两个键和三条链接,左链接指向的2-3树中的键都小于该节点,中 ...
- B树,B+树,红黑树应用场景AVL树,红黑树,B树,B+树,Trie树
B B+运用在file system database这类持续存储结构,同样能保持lon(n)的插入与查询,也需要额外的平衡调节.像mysql的数据库定义是可以指定B+ 索引还是hash索引. C++ ...
- 为什么HashMap使用红黑树而不是AVL树或者B+树
红黑树和AVL树都是最常用的平衡二叉搜索树. 但是,两者之间有些许不同: AVL树更加严格平衡,因此可以提供更快的査找效果.因此,对于查找密集型任务使用AVL树没毛病. 但是对于插入密集型任务,红黑树 ...
- 从2-3-4树谈到Red-Black Tree(红黑树)
从2-3-4树谈到红黑树 译者:July. 出处:http://blog.csdn.net/v_JULY_v . 在上一篇文章--从B树.B+树.B*树谈到R 树里已提到2-3-4树,那么本文,咱们就 ...
- 通过2-3-4树理解红黑树
前言 红黑树是数据结构中比较复杂的一种,最近与它交集颇多,于是花了一周的空闲时间跟它死磕,终于弄明白并实现了红黑树.写文总结一下,希望能给试图理解红黑树的同学一些灵感,也让我能记得更深刻. 在研究红黑 ...
- 树及树的算法(4) —— 红黑树
红黑树是在1972年由德国科学家鲁道夫·贝尔发明的,他称之为"对称二叉B树",它现代的名字是在 Leo J. Guibas和 Robert Sedgewick 于1978年写的一篇 ...
- 美团实习面试:熟悉红黑树是吧?能不能写一下?
点击关注公众号,Java干货及时送达 手写红黑树确实有点过分了,但我觉得写不出来也正常,只要理解就行 红黑树是数据结构中比较复杂的一种,最近与它交集颇多,于是花了一周的空闲时间跟它死磕,终于弄明白并实 ...
最新文章
- ASP .NET Core使用connection string连接MySQL/MariaDB,并设置UTF-8编码
- Oracle SCN
- 使用CGlib出现java.lang.NoClassDefFoundError: org/objectweb/asm/Type异常
- OPW-00001: Unable to open password-file
- Bigtable 论文翻译
- mysql结构优化_MySQL优化----数据库结构优化
- javaone_JavaOne 2012:观察与印象
- c语言中 字符串常量的界定符,c语言题库2
- Arduino笔记-对开关的基本认识
- 翻译文章第六章8-11
- 祝贺Terrylee博客园Post达到100篇
- ARM汇编开关终端cpsie/cpsid
- oracle unused 语法_Oracle教程之设置为unused 后如何恢复 ?
- 麦克纳姆轮全向移动机器人斜向直线运动分析
- localStorage的跨与实现方案
- OSSIM安装zabbix
- android x5webview截长图
- java 中文繁体转换简体
- 【日常】CCB网上银行“云宠物”喂食自动化脚本
- 会计信息质量可靠性的案例_浅谈会计信息可靠性(一)