一,红黑树性质。
由于二叉查找树知道,一个高度为h的二叉查找树可以实现任何一种基本的动态几何操作,如search,insert,minimum,delete,successor等操作,其时间都是O(h),这样树的高度低了就会执行的比较快,但是当树的高度较高时,操作的性能可能不比链表好。红黑树是许多“平衡的”查找树中的一种,他能保证在最坏的情况下,基本的动态集合操作的时间为O(lgn)。
二、红黑树旋转。
left-rotate(T, x)
y = right[x]
right[x] = left[y] // y的左子树变为x的右子树
parent[left[y]] = x
parent[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]] = y
left[y] = x // y的左孩子结点是x
parent[x] = y // x的父亲节点是y
三、红黑树插入。
rb-insert(T, z)
y = null
x = root[T]
while x != null
do y = x
if(key[x] < key[z])
then x = right[x]
else x = left[x]
parent[z] = y
if(y == null) //树是空的
then root[T] = z
else if key[z] < key[y]
then left[y] = z
else right[y] = z
left[z] = nil[T]
right[z] = nil[T]
color[z] = RED // 着色为红色
rb-insert-fixup(T, z)
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的父节点与祖节点进行一次右旋,并把父节点着黑色,原来的祖节点着红色。这些子树的红黑特性得到了恢复,而且子树的黑高度没有变化。另外,由于子树根节点已经是黑色了(这个节点不会出现父子同为红色的问题了),所以不必再向上递归了,此时整个树的红黑特性都已经是正确的了。
由于红黑树的删除比较复杂,放在下一篇。
网上发现不错的学习资料,分享一下:红黑树算法的层层剖析与逐步实现