Red-Black Tree 与 STL源码 (0)

由于STL中的关联式容器默认的底层实现都是红黑树,因此红黑树对于后续学习STL源码还是很重要的,有必要掌握红黑树的实现原理和源码实现。

一、红黑树 简介:


红黑树和AVL Tree(自平衡二叉查找树)类似,都是在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能。红黑树和AVL树的区别在于它使用颜色来标识结点的高度,它所追求的是局部平衡而不是AVL树中的非常严格的平衡。

二、红黑树定义:

一棵红黑树是指一棵满足下述性质的二叉搜索树(BST, binary search tree): 
  1. 每个结点或者为黑色或者为红色。 
  2. 根结点为黑色。 (NIL结点)
  3. 每个叶结点(实际上就是NULL指针)都是黑色的。 
  4. 如果一个结点是红色的,那么它的两个子节点都是黑色的(也就是说,不能有两个相邻的红色结点)。 
  5. 对于每个结点,从该结点到其所有子孙叶结点的路径中所包含的黑色结点数量必须相同。 

三、二叉查找树(Binary Search Tree):

在研究红黑树之前我们先了解下Binary Search Tree,二叉排序树或者是一棵空树,或者是具有下列性质的二叉树:

(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
(4)没有键值相等的节点。

我们关心的二叉查找树的逻辑结构,下面的两棵二叉树:


图1 二叉查找树。


(a)这一棵高度为3的二叉树,因为10比15小,所以10在15的左子树上;同理在以10为根的左子树里,7比10小所以7在左子树上,12在10为根的子树的右子树上;20在以15为根的右子树上。(b)这是一棵高度是4的二叉查找树,它的所有key与图(a)是一样的。在图(a)中,查找最坏的情况是7和12,它们需要经过3次比较才能找到,而图(b)最坏情况是20,需要经过4次比较才能找到。


要想二叉树的查找的花费时间小,我们尽可能让二叉树不出现类以于单链形态的二叉树,让树的高度尽量的低。对于高度为h的二叉查找树,从树根对叶子最坏的情况是比较h次。也就是说,对于高度为h的二叉查找树的最坏查找情况的运行时间是O(h)。二叉树的查找效率取决于树的高度。


typedef struct node_s node_t;
typedef struct tree_s tree_t;

/* define NIL is NULL */
#define NIL 0
#define init(x) x->l=x->r=x->p=NIL  

/* node structure*/
struct node_s {
    int		 k;	/*key*/
    node_t	*p;	/*parent*/
    node_t	*l;	/*left*/
    node_t	*r;	/*right*/
};

/* tree structure*/
struct tree_s {
    node_t * root;
};

/* search */
node_t * search(tree_t *T,int k) 
{
    node_t * x;
    x = T->root;
    while (x != NIL) {
        if (k == x->k) {
            break;
        }
        if (k < x->k) {
            x = x->l;
        } else {
            x = x->r;
        }
    }
    return x;
}

/*find the value max node*/
node_t * max(node_t * x) 
{
    while (x->r != NIL) {
        x = x->r;
    }
    return x;
}

/*find the value min node*/
node_t * min(node_t *x) 
{
    while (x->l != NIL) {
        x = x->l;
    }
    return x;
}

/*
to find node y 's successor , as following.
if y has r-child tree, then its successor must be the min node of r-child tree
else we can find one node which predecessor is y, and it is y's successor
      E
	/   
   A
    \
     D
    /
   B
    \
	 C
	 
the sort:ABCDE

x=D 
or
x=B

*/
/*find successor of the node*/
node_t * successor(node_t *x)
{
    node_t *y;
    if (x->r != NIL) {
        y = min(x->r);
    } else {
        y = x->p;
        while ((y != NIL) && (y->r == x)) {
            x = y;
            y = x->p;
        }
    }
    return y;
}



/* same as successor*/
/*find predecessor of the node*/
node_t * predecessor(node_t *x)
{
    node_t *y;
    if (x->l != NIL) {
        y = max(x->l);
    } else {
        y = x->p;
        while ((y != NIL) && (y->l == x)) {
            x = y;
            y = x->p;
        }
    }
    return y;
}

/*中序遍历*/
void inorder(tree_t * T,void (*visit)(node_t *))
{
    node_t *x;
    x = T->root;
    if (x == NIL) {
        x = min(x);
        while (x != NIL) {
            visit(x);
            x = successor(x);
        }
    }
    return ;
}

/*insert a node*/
int insert(tree_t *T,node_t *z)
{
    node_t *x,*y;
    x = T->root;
    y = x;
    while (x != NIL) {
        y = x;
        if (z->k == x->k) {
            return 1;
        }
        if (z->k < x->k) {
            x = x->l;
        } else {
            x = x->r;
        }
    }
    init(z);
    if (y == NIL) {
        T->root = z;
    } else {
        if (z->k < y->k) {
            y->l = z;
        } else {
            y->r = z;
        }
        z->p = y;
    }
    return 0;
}

/*替换*/
void _transplant(tree_t *T,node_t *u,node_t *v) 
{
    if (u->p == NIL) {
        T->root = v;
    } else {
        if (u->p->l == u) {
            u->p->l = v;
        } else {
            u->p->r = v;
        }	
    }
    if (v != NIL) {
        v->p = u->p;
    }
    return ;
}
/*删除*/
int remove(tree_t *T,node_t *z)
{
    do {
        node_t * y;
        if (z->r == NIL) {
            _transplant(T,z,z->l);
            break;
        }
        y = min(z->r);
        if (y != z->r) {
            _transplant(T,y,y->r);
            y->r = z->r;
            y->r->p = y;
        }
        _transplant(T,z,y);
        y->l = z->l;
        if (z->l != NIL) {
            z->l->p = y;
        }
    } while (0);
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值