红黑树是"平衡的"二叉查找树(PS: 关于二叉查找树的内容见链接)。普通的二叉查找树,在最坏情况下基本操作的运行时间为Θ(n),大部分的操作的最坏情况运行时间与树的高度成正比,对于相同的数据如何构造出一棵高效的二叉查找树(即高度尽量小)(如下图)
图a为高效的二叉查找树,图b为低效的二叉查找树
造成图b中的二叉查找树低效的原因在于建树的时候结点插入的顺序不恰当,选取关键字为2的结点(最小关键字结点)作为根结点使得所有的结点都位于根结点的右子树里。
更糟糕是所有的结点都在同一条路上,这时候就相当于在链表上进行操作。
但是普通的二叉查找树不会自动调整,使自己的尽量平衡(根结点的左右子树的高度接近相同),它只会根据插入结点的关键字来判断插入的位置。为了使其可以接近平衡,我们可以在结点里添加一些属性,然后根据这些属性来动态调整树的形状。(例如红黑树添加了颜色属性,AVL树添加了结点高度属性。)
红黑树的基本性质:
颜色属性:颜色为红色(RED)或者黑色(BLACK)。
NIL结点:指向二叉查找数的外结点(叶子)指针,颜色为黑色;某些结点的父结点或者子结点指向NIL结点,相当于哨兵。(即为书中的nil[ T ])
红黑性质:1、每个结点的颜色为红色或者黑色
2、根结点的颜色为黑色
3、每个叶结点都是黑色
4、如果一个结点是红色的,那么它的两个儿子都是黑色的
5、对于每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点
黑高度:从该结点x出发(不包括该结点)到达叶结点的任意一条路径上,黑色结点的个数为该结点的黑色高度,用bh(x)
具体如下图所示(深色为黑色结点,浅色为红色结点):
下为红黑树结点结构体、红黑树结构体和NIL指针等基本实现
1 #define RED 1 2 #define BLACK 0 3 4 typedef struct RB_TreeNode { 5 int value; 6 int color; 7 struct RB_TreeNode * parent; 8 struct RB_TreeNode * left; 9 struct RB_TreeNode * right; 10 }RB_TreeNode; //红黑树结点结构体 11 12 typedef struct RB_Tree { 13 RB_TreeNode * root; 14 }RB_Tree; //红黑树结构体,根结点 15 16 RB_TreeNode NILL = { -1, BLACK, NULL, NULL, NULL }; 17 RB_TreeNode *NIL = &NILL; //NIL结点指针