目录
红黑树(red-black-tree)
一.红黑树的定义和性质
红黑树是一种二叉查找树,在每个结点上增加一个存储位表示结点的颜色,,可以是red或者是black。通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树保证没有一条路径会比其他路径长出两倍,因而是接近平衡的。可以证明,一颗有n个点内结点的红黑树的高度至多为2lg(n+1).
一颗红黑树应满足以下性质:
1.每个结点是红的或者是黑的
2.根结点是黑的
3.每个叶结点(NIL)是黑的
4.如果一个结点是红的,则它的两个儿子都是黑的
5.对于每个结点,从该结点到其他子孙结点的所有路径上包含相同数目的黑结点
(省略叶节点NIL)
二.红黑树的结构
树中的每个结点包括color,key,left,right,fa,分别表示结点的颜色,值,左儿子,右儿子,父结点。如果某结点没有一个子结点或者父结点,则该结点的相应指针指向NULL,这里定义一个哨兵表示NULL.
struct RB_Node{ //树结点
int key;
bool color;
RB_Node *fa, *left, *right;
};
struct RB_tree{ //红黑树(red-black-tree)
RB_Node* root; //红黑树的根结点
RB_Node* NIL; //红黑树的叶节点(哨兵)
RB_tree(){
NIL = new RB_Node();
NIL->color = black;
root = NIL;
}
void RB_inorder(RB_Node* x); //中序遍历输出一颗红黑树
void RB_printf(RB_Node* x, int n = 0); //逆时90度输出一颗红黑树
RB_Node* RB_search(RB_Node* x, int k); //查找key值为k的树结点
RB_Node* RB_minnum(RB_Node* x); //查找以x为根结点的树的最小值
RB_Node* RB_maxnum(RB_Node* x); //查找以x为根结点的树的最大值
RB_Node* RB_successor(RB_Node* x); //查找x的后继结点
RB_Node* RB_precursor(RB_Node* x); //查找x的前驱结点
void RB_left_rotate(RB_Node* x); //左旋
void RB_right_rotate(RB_Node* x); //右旋
void RB_insert(RB_Node* x); //插入新的树结点
RB_Node* RB_delete(RB_Node* x); //删除树结点
void RB_insert_fixup(RB_Node *x); //插入结点后,调整红黑树的结构保持红黑树的性质
void RB_delete_fixup(RB_Node *x); //删除结点后,调整红黑树的结构保持红黑树的性质
}T;
三.输出一颗红黑树
1.可以用中序遍历的方式按照排序顺序输出树中的关键字,设x是树结点的某一点,则中序遍历是先输出x的左子树,再输出x结点的值,然后再输出x的右子树
2.有时候按照顺序排序输出一颗红黑树并不能非常直观的看出树的结点之间的关系,可以用稍微修改后的中序遍历方法,逆时针90度输出一颗二叉树。
void RB_tree::RB_inorder(RB_Node *x){ //中序遍历输出一颗红黑树
if (x != NIL){
RB_inorder(x->left);
printf("%d ", x->key);
RB_inorder(x->right);
}
}
void RB_tree::RB_printf(RB_Node *x, int n){ //逆时90度输出一颗红黑树
if (x == NIL){
for (int i = 0; i<n; i++){
printf(" ");
}
printf("NIL\n");
return;
}
RB_printf(x->right, n + 1); //输出右子树
for (int i = 0; i<n; i++){ //输出长为n的" "空格
printf(" ");
}
if (n >= 0){
printf("%d%c-->\n", x->key,x->color?'b':'r'); // 输出该点的数值
}
RB_printf(x->left, n + 1); //输出左子树
}