算法学习之数据结构之红黑树(一)
来源:互联网 发布:五大数据存储 编辑:程序博客网 时间:2024/06/05 13:34
一,红黑树性质。
由于二叉查找树知道,一个高度为h的二叉查找树可以实现任何一种基本的动态几何操作,如search,insert,minimum,delete,successor等操作,其时间都是O(h),这样树的高度低了就会执行的比较快,但是当树的高度较高时,操作的性能可能不比链表好。红黑树是许多“平衡的”查找树中的一种,他能保证在最坏的情况下,基本的动态集合操作的时间为O(lgn)。
红黑树的性质。红黑树是一种二叉查找树,,每一个节点增加一个存储位表示节点的颜色,为红色或者黑色。红黑树确保没有一条路径会比其他路径长出两倍。因而是接近平衡的。
树的每个节点包含五个域:color, parent, key, left, right。一个二查找树如果满足如下红黑性质,则为一个红黑树。
1)每个节点或是红的,或是黑的。
2)根节点是黑。
3)每个叶节点(NIL)是黑的。
4)如果一个节点是红的, 则它的两个孩子都是黑的。
5)对每个节点,从该节点到其子孙节点的所有路径上包含相同数目的黑节点。
从某个节点x出发到达一个叶节点的任意一条路径上,黑色节点的个数成为该节点x的黑高度。
一个有n个内节点的红黑树的高度至多为2lg(n+1)
二、红黑树旋转。
当对红黑树上进行insert和delete时,对树进行了修改,结果可能会违反红黑树的性质,所以需要改变树中的节点的颜色和指针结构,即需要进行旋转。
左旋,假设它的右孩子节点y不是nil[T];x可以为树内任意右孩子不是nil[T]的节点,左旋以x和y之间的链为轴进行,它使y成为该子树新的根,x成为y的左孩子节点,而y的左孩子节点为x的右孩子。
伪代码如下:
left-rotate(T, x)y = right[x]right[x] = left[y] // y的左子树变为x的右子树parent[left[y]] = xparent[y] = parent[x] // x的父亲节点是y的父亲节点if parent[y] == null then root[T] = y // x的根节点是根节点则置为y else if x == left[parent[x]] // 如果x是其父节点的左孩子节点,则将y置为x父节点的左孩子节点否则置为其父节点的右孩子节点 then left[parent[x]] = y else right[parent[x]] = yleft[y] = x // y的左孩子结点是xparent[x] = y // x的父亲节点是y
三、红黑树插入。
分为两部分,先把节点插入红黑树中,并着为红色,然后进行修补以保持红黑树的性质。先看前一部分的伪代码,和二叉查找树的插入大部分类似。
rb-insert(T, z)y = nullx = root[T]while x != null do y = x if(key[x] < key[z]) then x = right[x] else x = left[x]parent[z] = yif(y == null) //树是空的 then root[T] = z else if key[z] < key[y] then left[y] = z else right[y] = zleft[z] = nil[T]right[z] = nil[T]color[z] = RED // 着色为红色rb-insert-fixup(T, z)
就最后四行和二叉查找树不一样,其他的都一样,并着为红色,然后进行修补以保持红黑树的性质,接下来看rb-insert-fixup(T, z),将插入的节点z着为红色以后,可能破坏的性质有性质2和性质4,所以我们要做的就是恢复性质2和性质4.先大致说一下判断情况:
1,首先让一个指针y指向z的叔叔节点(z是要删除的节点)。
2,如果y是红色的,CASE1。则使z的父亲节点和叔叔节点改为黑色,z的祖父及诶单改为红色。然后z转移到z的祖父节点。
3,当y的颜色是黑色时,
①.首先判断z是否是其父亲结点的右儿子,若是,则调整为左儿子(用旋转)。 CASE2。
②.其次使z的父亲结点颜色为黑,z的祖父结点颜色为红,并以z的祖父结点为轴右旋,CASE3。看伪代码吧。
伪代码如下:
rb-insert-fixup(T, z)while color[p[z]] = RED do if parent[z] == left[parent[parent[z]]] // z节点的父亲节点是其祖父节点的左孩子节点 then y = right[parent[parent[z]]] // y为z节点的祖父节点的右孩子节点,即叔叔节点 if color[y] == RED // 叔叔节点为红色 CASE1 then color[parent[z]] = black // 父亲节点黑色 color [y] = black // 叔叔节点黑色 color[parent[parent[z]] = red // 祖父节点红色 z = parent[parent[z]] esle if z == right[parent[z]] // 叔叔节点是黑的,且z为父节点的右孩子节点 CASE2 then z = parent[z] left-rotate(T, z) // 左旋转 // CASE3 color[parent[z]] = black //把父节点着黑色 color[parent[parent[z]]] = red //原来的祖节点着红色 right-rotate(T, z) else // z节点的父亲节点是其祖父节点的右孩子节点 操作和左孩子节点一样color[root[T]] = black // 最后把根节点置为黑色
具体解释如下:
根据Z的父节点是Z的祖节点的左子节点还是右子节点,分为两组对称的情况,每组有3种情况。以Z的父节点是Z祖节点的左子节点为例:
第一种:Z的“叔父”节点是红色。
如上图所示,在这种情况下,将父、叔节点都着为黑色,再将子树根节点着为红色,那么子树的黑高度没有发生改变,而且红黑性质得得到了调整。此时,再将Z指向子树的根节点,向上递归恢复红黑特性。
第二种:Z的“叔父”节点是黑色的,Z的父节点的右子节点。
如上图,将Z本身与其父节点进行一次左旋,让Z指向原来的父节点,就可以调整为情况三,下面看情况三。
第三种:Z的“叔父”节点是黑色的,Z的父节点的左子节点。
如上图,将Z的父节点与祖节点进行一次右旋,并把父节点着黑色,原来的祖节点着红色。这些子树的红黑特性得到了恢复,而且子树的黑高度没有变化。另外,由于子树根节点已经是黑色了(这个节点不会出现父子同为红色的问题了),所以不必再向上递归了,此时整个树的红黑特性都已经是正确的了。
由于红黑树的删除比较复杂,放在下一篇。
网上发现不错的学习资料,分享一下:红黑树算法的层层剖析与逐步实现
- 算法学习之数据结构之红黑树(一)
- 学习笔记之数据结构与算法(一)
- 数据结构与算法学习之(一):基本概念介绍
- 算法学习之数据结构之红黑树(二)
- 数据结构算法之排序(一)
- 数据结构之排序算法(一)
- java 数据结构学习之(一)数组
- 数据结构学习之顺序表(一)
- 数据结构学习之路(一)
- 数据结构算法学习之路
- 数据结构学习之排序算法
- 数据结构学习之冒泡算法
- linux 学习之数据结构算法
- 数据结构之简单算法学习
- 数据结构与算法学习笔记之--数据结构
- 数据结构与算法分析c版的学习笔记之Lists,Stacks,and Queues(一)
- 数据结构经典算法学习之河内之塔(汉诺塔)
- 数据结构与算法整理之排序(一)
- 初学Android,数据存储之File存储(四十二)
- 每次职业转身,正因王牌在握,李开复才能真正追随我心
- linux下不能向255.255.255.255发送udp广播
- 设计模式六:桥梁模式
- Python——待解决 求解救!!!!
- 算法学习之数据结构之红黑树(一)
- javascript 判断是否为正整数
- flex中通过https与服务器交互
- 刚开始学习移动开发的小笔记
- 通讯录实时云同步、云备份
- 查找当前用户的所有数据库对象的依赖关系
- Android 实现图片倒影效果
- UVa 10387 - Billiard
- Objective-C特点及特征