红黑树
红黑树是一棵二叉搜索树,它在每个节点上增加了一个存储位来表示节点的颜色,可以是RED或BLACK。树中每个节点包含5个属性:color、key、left、right和p,如果一个节点没有子节点或父节点,则该节点相应指针属性的值为NIL,一棵红黑树满足下面红黑性质的二叉搜索树:
- 每个节点或是红色的,或是黑色的
- 根节点是黑色的
- 每个叶节点(NIL)是黑色的
- 如果一个节点是红色的,则它的两个子节点都是黑色的
- 对每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点
如下图(a)为一棵红黑树,而在图(b)中,不是用一个个NIL表示,而是用一个总黑色的哨兵T.nil来代替,它的黑高也被省去,根节点的父节点也是这个哨兵。
从某个节点 x x x出发(不含该节点)到达一个叶节点的任意一条简单路径上的黑色节点个数称为该节点的黑高,记为 b h ( x ) bh(x) bh(x)。从红黑树的性质得出,一棵有 n n n个内部节点的红黑树的高度至多为 2 l g ( n + 1 ) 2lg(n+1) 2lg(n+1)
旋转
搜索树操作insert和delete在含有 n n n个关键字的红黑树上,运行花费时间为 O ( l g n ) O(lgn) O(lgn)。由于这两个操作对树做了修改,可能违反了红黑性质,为了维护这些性质,必须要改变树中某些节点的颜色以及指针结构。指针结构的修改是通过旋转(ratation)来完成的,这是一种能保持二叉搜索树性质的搜索树局部操作。如下图,给出了两种旋转:左旋和右旋。左旋以 x x x到 y y y的链为“支轴”进行,它使 y y y成为该子树新的根节点, x x x成为 y y y的左孩子, y y y的左孩子成为 x x x的右孩子。
python实现旋转如下:
#左旋转
def left_rotate(self, x):
# set y
y = x.rchild
# turn y left subtree into x right subtree
x.rchild = y.lchild
if y.lchild != self.nil:
y.lchild.parent = x
# link x parent to y
y.parent = x.parent
if x.parent == self.nil:
# x is root
self.root = y
elif x == x.parent.lchild:
x.parent.lchild = y
else:
x.parent.rchild = y
# put x on y left
y.lchild = x
x.parent = y
#右旋转
def right_rotate(self, y):
# set x
x = y.lchild
# turn x right subtree into y left subtree
y.lchild = x.rchild
if x.rchild != self.nil:
x.rchild.parent = y
# link y parent to x
x.parent = y.parent
if y.parent == self.nil:
# x is root
self.root = x
elif y == y.parent.lchild:
y.parent.lchild = x
else:
y.parent.rchild = x
# put y on x right
x.rchild = y
y.parent = x