数据结构之四(平衡查找树之一--红黑树)
由二叉查找树随机情况下O(lgn)的操作(增、删、查)时间,因此希望得到一种下最坏情况O(lgn)的操作时间。
由二叉树操作时间和树高相关,因此考虑将二叉树的高度保持为O(lgn),从而达到目的。
平衡树包括:AVL,2-3树,2-3-4树,B树(B+,B*),R-B树(红黑树),Skip lists(跳跃表),Treap(树堆)
1. 红黑树(R-B树)
红黑树是一种二叉查找树。节点的数据域包括5个域:color,key,left,right,p。
红黑树需要将树扩展为“满树”,树的最外层增加一层NIL节点,每个非NIL节点都有两个孩子,原树的节点都为新树的内部节点,所有叶子节点为NIL节点。
另外满足:
Ø 每个节点或者为红的,或者为黑的。
Ø 根为黑的。
Ø 叶节点(NIL)为黑的。
Ø 如果节点为红的。则其两个孩子都为黑的。
Ø 对于任何一个节点。从该节点到其任何叶节点,路径包含的黑节点树相同。(如果黑节点树不计算该节点,则黑节点树称为黑高度)。
1.1. 有n个内部节点的红黑树高度为2*lg(n+1)。从而为O(lgn)的。
证明方法:一归纳。
法二:将红节点收缩到父节点(黑节点),从而变为全为黑节点的满二叉树。这也可以体现出R-B树与2-3树,2-3-4树的关系。
1.2. 红黑树中每个节点到终端节点的最长路径最多为最短路径的2倍。
1.3. 旋转操作
旋转相当于节点往那边下降。
左旋转要求右孩子非NIL,旋转在节点与其右孩子之间进行。
右旋转要求左孩子非NIL,旋转在节点与其左孩子之间进行。
需要注意指针的调整。最后要考虑新的根是否为整个树的根,否则要调整x的父的左(或右)孩子为新的根。
1.4. 红黑树的插入
l 以普通二叉查找树的插入将节点插入树中。
l 新节点设定为红色。
l 调整节点颜色,以便满足红黑性质。
新节点的父节点为红色时才会破坏红黑树的性质,且只破坏了红节点的孩子只能为红色的性质。因此需要将不平衡往上移动。
且此时,父节点的父节点(祖父节点)肯定为黑的,因为父节点为红。
旋转调整的情况:
Ø 父节点的兄弟节点为红(情况一):(这时候节点,父节点,父节点的兄弟节点为红;祖父节点为黑)这时候将父节点,父节点的兄弟节点和祖父节点变色(父节点和父节点的兄弟当然变为黑的了,祖父节点变为红色的了)。这种调整后,黑高度不会改变。只将不平衡往上移动到祖父节点。继续调整祖父节点。
Ø 父节点的兄弟节点为黑,且父节点为祖父节点的左孩子:(这时候节点,父节点为红;父节点兄弟节点,祖父节点为黑),如果节点为父节点的右孩子(情况二),则将父节点左旋转(往外旋转,旋转红色的这两个节点)。原节点变为父节点,原父节点变为子节点,且为左孩子。将不平衡点下降到原父节点,新的子节点。(变为情况三)
Ø 父节点的兄弟节点为黑,且父节点为祖父节点的左孩子:(这时候节点,父节点为红;父节点兄弟节点,祖父节点为黑),如果节点为父节点的左孩子(情况三),则将祖父节点右旋转(将斜的链变为平衡的),原父节点取代祖父节点位置,原祖父节点变为原父节点的右孩子。并改变原祖父节点和原父节点颜色(从而新的根为原父节点,为黑的,其左右孩子分别为原节点和原祖父节点,现在都变为红色)。调整结束。
相对应的,父节点如果祖父节点的右孩子,则相应的情况进行相反的旋转。
情况一下只会调整。
情况二会转为情况三。
情况三做一次调整及完成,调整结束。
整个插入过程最多进行两次旋转。
有调整,则根可能被改色,因此最后修改根为黑色的。
1.5. 红黑树删除