红黑树

秉承talk is cheap, show me the code的理念,废话不多说,上代码。

头文件

#ifndef __RBTREE_H
#define __RBTREE_H

#ifdef __cplusplus
extern "C" {
#endif

/* 遍历顺序 */
typedef enum
{
    RB_TREE_ORDER_PRE,
    RB_TREE_ORDER_IN,
    RB_TREE_ORDER_POST
}RBORDER_E;

typedef struct rbnode_s
{
    struct rbnode_s *child[2];	/* 0:left, 1:right */
	unsigned char color;
	unsigned char lr;			/* 表征这个节点是父节点的左还是右子节点 */
    unsigned short flags;       /* FLAGS */
}rbnode_t;

typedef int  (*rbcmp)(rbnode_t *node, void* key);
typedef int  (*rbwalk)(rbnode_t *node, void* arg);
typedef void (*rbdestroy)(rbnode_t *node, void* arg);

typedef struct
{
    rbnode_t *tree;
    rbnode_t nil;
    rbcmp    cmp;
}rbtree_t;

void rbtree_init(rbtree_t *tree, rbcmp cmp);
void rbtree_add(rbtree_t *tree, rbnode_t *node, void *key);
void rbtree_destroy(rbtree_t *tree, rbdestroy pcb, void *pcbarg, RBORDER_E order);
int  rbtree_walk(rbtree_t *tree, rbwalk pcb, void *pcbarg, RBORDER_E order);
rbnode_t *rbtree_getmini(rbnode_t *node);
rbnode_t *rbtree_del(rbtree_t *tree, void* key);
rbnode_t *rbtree_get(rbtree_t *tree, void* key);

#ifdef RBTREE_TEST
typedef char* (*rbtreeprintcb)(rbnode_t *node, void *arg);
void rbtree_print(rbtree_t *tree, FILE *fp, rbtreeprintcb pcb, void *pcbarg);
#endif


#ifdef __cplusplus
}
#endif


#endif

源文件

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <rbtree.h>



#ifdef __cplusplus
extern "C" {
#endif

#define RB_TREE_MAX_DEPTH   64

#define RB_TREE_COLOR_BLACK     (1)
#define RB_TREE_COLOR_RED       (0)

#define RB_TREE_LR_LEFT         (0)
#define RB_TREE_LR_RIGHT        (1)

#define RB_TREE_FLAGS_NIL       (1<<0)

#define RB_TREE_IS_NIL(node)            (0 != (RB_TREE_FLAGS_NIL&((node)->flags)))
#define RB_TREE_SET_NIL(node)           ((node)->flags |= RB_TREE_FLAGS_NIL)

#define RB_TREE_IS_BLACK(node)          (RB_TREE_COLOR_BLACK == (node)->color)
#define RB_TREE_IS_RED(node)            (RB_TREE_COLOR_RED == (node)->color)
#define RB_TREE_SET_BLACK(node)         ((node)->color = RB_TREE_COLOR_BLACK)
#define RB_TREE_SET_RED(node)           ((node)->color = RB_TREE_COLOR_RED)
#define RB_TREE_SET_COLOR(node, cl)     ((node)->color = cl)
#define RB_TREE_COLOR_REVERSE(node)     ((node)->color = 1-(node)->color)

#define RB_TREE_SET_LEFT(node)          ((node)->lr = RB_TREE_LR_LEFT)
#define RB_TREE_SET_RIGHT(node)         ((node)->lr = RB_TREE_LR_RIGHT)
#define RB_TREE_SET_CHILD(P, L, C)      (P)->child[L]=(C); (C)->lr=(L)
#define RB_TREE_LR_INDEX(node)          ((node)->lr)
#define RB_TREE_LR_OTHER(node)          (1-RB_TREE_LR_INDEX(node))
#define RB_TREE_LR_REVERSE(lr)          (1-(lr))

#define RB_TREE_BROTHER(parent, node)   ((parent)->child[RB_TREE_LR_OTHER(node)])

#define RB_TREE_INIT_NODE(tree, node)       (node)->child[0]=(node)->child[1]=&(tree)->nil;(node)->flags=0;RB_TREE_SET_RED(node)

static int _rb_walk_pre(rbnode_t *node, rbwalk pcb, void *pcbarg)
{
    int ret = 0;
    if (RB_TREE_IS_NIL(node)
     || 0 != (ret=pcb(node, pcbarg))
     || 0 != (ret=_rb_walk_pre(node->child[RB_TREE_LR_LEFT], pcb, pcbarg))
     || 0 != (ret=_rb_walk_pre(node->child[RB_TREE_LR_RIGHT], pcb, pcbarg))) {
        return ret;
    } else {
        return 0;
    }
}

static int _rb_walk_in(rbnode_t *node, rbwalk pcb, void *pcbarg)
{
    int ret = 0;
    if (RB_TREE_IS_NIL(node)
     || 0 != (ret=_rb_walk_in(node->child[RB_TREE_LR_LEFT], pcb, pcbarg))
     || 0 != (ret=pcb(node, pcbarg))
     || 0 != (ret=_rb_walk_in(node->child[RB_TREE_LR_RIGHT], pcb, pcbarg))) {
        return ret;
    } else {
        return 0;
    }
}

static int _rb_walk_post(rbnode_t *node, rbwalk pcb, void *pcbarg)
{
    int ret = 0;
    if (RB_TREE_IS_NIL(node)
     || 0 != (ret=_rb_walk_post(node->child[RB_TREE_LR_LEFT], pcb, pcbarg))
     || 0 != (ret=_rb_walk_post(node->child[RB_TREE_LR_RIGHT], pcb, pcbarg))
     || 0 != (ret=pcb(node, pcbarg))) {
        return ret;
    } else {
        return 0;
    }
}

static void _rb_destroy_pre(rbnode_t *node, rbdestroy pcb, void *pcbarg)
{
    rbnode_t *left;
    rbnode_t *right;
    
    if (RB_TREE_IS_NIL(node)) {
        return;
    } else {
        left = node->child[RB_TREE_LR_LEFT];
        right = node->child[RB_TREE_LR_RIGHT];
        pcb(node, pcbarg);
        _rb_destroy_pre(left, pcb, pcbarg);
        _rb_destroy_pre(right, pcb, pcbarg);
    }
}

static void _rb_destroy_in(rbnode_t *node, rbdestroy pcb, void *pcbarg)
{
    rbnode_t *right;
    
    if (RB_TREE_IS_NIL(node)) {
        return;
    } else {
        _rb_destroy_in(node->child[RB_TREE_LR_LEFT], pcb, pcbarg);
        right = node->child[RB_TREE_LR_RIGHT];
        pcb(node, pcbarg);
        _rb_destroy_in(right, pcb, pcbarg);
    }
}

static void _rb_destroy_post(rbnode_t *node, rbdestroy pcb, void *pcbarg)
{
    if (RB_TREE_IS_NIL(node)) {
        return;
    } else {
        _rb_destroy_post(node->child[RB_TREE_LR_LEFT], pcb, pcbarg);
        _rb_destroy_post(node->child[RB_TREE_LR_RIGHT], pcb, pcbarg);
        pcb(node, pcbarg);
    }
}

void rbtree_init(rbtree_t *tree, rbcmp cmp)
{
    tree->tree = &tree->nil;
    tree->cmp = cmp;
    tree->nil.child[0] = tree->nil.child[1] = NULL;
    tree->nil.color = RB_TREE_COLOR_BLACK;
    tree->nil.lr = RB_TREE_LR_LEFT;
    tree->nil.flags = 0;
    RB_TREE_SET_NIL(&tree->nil);    
}

rbnode_t *rbtree_getmini(rbnode_t *node)
{
    rbnode_t *prev = NULL;
    
    while (!RB_TREE_SET_NIL(node)) {
        prev = node;
        node = node->child[RB_TREE_LR_LEFT];
    }
    
    return prev;
}

/*
增加一个节点
N表示新增节点, .B表示黑色, .R表示红色, .X表示黑或者红。

1. 父节点是黑色的,直接平衡   

          P.B
          / \
         /   \
       N.R   C.X
       
2. 父节点是红色的,那么:
   主要操作是为了消除“双红”,且不能破坏左右子树的黑平衡
   P 应该有父节点(根节点必须是黑色)
   P.right 应该是空(红节点孩子必须为黑 & 到叶子路径上黑节点数目必须相同) 
     假设 PP.right 为红色(空的情况请看 3.) 
     
   修改P,U,PP的颜色,如果 PP.father 为黑,完成。
   否则继续按4.处理PP

            PP.B                       PP.R                                  
             / \                        / \
            /   \                      /   \
          P.R   U.R     -------->    P.B   U.B
          / \     \                  / \     \
         /   \     \                /   \     \
       N.R   NULL  NULL           N.R   NULL  NULL
 
 
3.  
            PP.B                        P.B                                  
             / \                        / \
            /   \                      /   \
          P.R   NULL     -------->   N.R  PP.R
          / \                        / \     \
         /   \                      /   \     \
       N.R   NULL                NULL   NULL  NULL

4. 如果X是红,重复步骤2,否则步骤3(下图)         

              PPPP.B                    PPP.B
               / \                       / \
              /   \                     /   \
           PPP.R   X                PP.R   PPPP.R                               
             / \                    / \      /  \
           /     \                 /   \    /    \
        PP.R     UU.B     --->    A    B   UU.B   X
         / \      / \                      / \
        /   \    /   \                    /   \     
       A    B   C     D                  C    D
 */

void rbtree_add(rbtree_t *tree, rbnode_t *node, void *key)
{
    rbnode_t **path[RB_TREE_MAX_DEPTH];
    rbnode_t *uncle;
    rbnode_t *A;
    rbnode_t *B;
    rbnode_t *C;
    int      depth = 0;
    int      ret = 0;
    unsigned char lr; //参考lr

    RB_TREE_INIT_NODE(tree, node);

    /* 查找树插入 */
    path[depth] = &tree->tree;
    while (!RB_TREE_IS_NIL(*path[depth])) {
        A=*path[depth];
        ret = tree->cmp(A, key);
        if (ret > 0) {
            path[++depth] = &A->child[RB_TREE_LR_RIGHT];
        } else if (ret < 0) {
            path[++depth] = &A->child[RB_TREE_LR_LEFT];
        } else {
            return;
        }
    }
    *path[depth] = node;
    if (ret > 0) {
        RB_TREE_SET_RIGHT(node);
    } else {
        RB_TREE_SET_LEFT(node);
    }

    /* re-banlance*/
    while (depth>1 && RB_TREE_IS_RED(*path[depth-1]))
    {
        A = *path[depth-2];
        B = *path[depth-1];
        C = *path[depth];
        uncle = RB_TREE_BROTHER(A, B);

        /* 3. */
        if (RB_TREE_IS_BLACK(uncle)) {
            if (RB_TREE_LR_INDEX(C) == RB_TREE_LR_INDEX(B)) {/*A-B-C中B、C的左右属性一致,那么B在中间*/
                /*
                           A.B                B.B                A.B                B.B
                           / \                / \                / \                / \
                         Y.B B.R   ---->    A.R  C.R           B.R Y.B   ---->    C.R  A.R
                             / \            / \                / \                     / \
                           X.B C.R        Y.B X.B            C.R X.B                 X.B Y.B
                */
                rbnode_t *X = B->child[RB_TREE_LR_OTHER(C)];
                rbnode_t *Y = A->child[RB_TREE_LR_OTHER(C)];
                lr = RB_TREE_LR_INDEX(C);   // C的左右属性没变,以这个为参考
                
                *path[depth-2] = B; B->lr = A->lr; // 不能用RB_TREE_SET_CHILD,因为path[depth-3]可能指向tree->tree
                RB_TREE_SET_CHILD(B, RB_TREE_LR_REVERSE(lr), A); //B->A
                RB_TREE_SET_CHILD(A, lr, X); //A->X

                RB_TREE_SET_BLACK(B);
                RB_TREE_SET_RED(A);
            } else {
                /*
                           A.B                C.B               A.B                 C.B
                           / \              /     \             / \               /     \
                         B.R Y.B  ---->   B.R     A.R         Y.B B.R   ---->   A.R     B.R
                         / \             /   \   /   \            / \          /   \   /   \
                       X.B C.R         X.B  M.B N.B  Y.B        C.R X.B      Y.B  N.B M.B  X.B
                           / \                                  / \
                          M   N                                N   M
                */
                rbnode_t *X = B->child[RB_TREE_LR_INDEX(B)];
                rbnode_t *Y = A->child[RB_TREE_LR_OTHER(B)];
                rbnode_t *M = C->child[RB_TREE_LR_INDEX(B)];
                rbnode_t *N = C->child[RB_TREE_LR_OTHER(B)];
                lr = RB_TREE_LR_INDEX(B);  // B的左右属性没变,以这个为参考

                *path[depth-2] = C; C->lr=A->lr;
                RB_TREE_SET_CHILD(A, lr, N);   //A->N
                RB_TREE_SET_CHILD(C, lr, B);   //C->B
                RB_TREE_SET_CHILD(C, RB_TREE_LR_REVERSE(lr), A);   //C->A
                RB_TREE_SET_CHILD(B, RB_TREE_LR_REVERSE(lr), M);   //B->M

                RB_TREE_SET_BLACK(C);
                RB_TREE_SET_RED(A);
            }
            break;
        } else {/* 2. */
            RB_TREE_SET_BLACK(B);
            RB_TREE_SET_BLACK(uncle);
            RB_TREE_SET_RED(A);
            depth -= 2;
        }
    }
    RB_TREE_SET_BLACK(*path[0]);
}

/*
Del a node from a rbtree
先按照普通查找树来删除。0/1孩子直接删,2孩子用右子树最小节点替换。
A. 待删除节点是红色的,直接删除,依然平衡
B. 删除的是黑色的节点,那么黑平衡就被打破了,处理措施:
    1、如果子节点为红色,那红改黑就好了(增加本树的黑点)
    2、否则需要想办法减少兄弟树的黑点,然后继续往上处理

具体分析一下情况B。搜索树删除实际上删除的都是叶端节点(只有0/1个子树)。
另外根据红黑树的要求,该删除点不可能有黑色的子节点(黑平衡),如果是红
子节点,那么改颜色即可(B.1)。下面分析一下没有子节点的情况:
P是被删除节点的父亲节点(左边是被破坏的子树):
            P.X
            / \
          L.B  R.X
L刚开始的时候是NIL,认为是黑色的,后续调整过程也应该是黑色的,否则直接
染红即可(B.1),无需继续调整。那么我们现在需要减少R.X子树的黑色,然后
继续处理P.X。
1. 兄弟(A)是黑色的,且孩子也都是黑色的
            P.X                   P.X
            / \                   / \
          C.B  A.B      --->    C.B  A.R
               / \                   / \
             X.B Y.B               X.B Y.B
   则把A染成红色,这样C子树和A子树的黑色点数就相同了,然后继续处理P子树:
   如果P是红色,则P变黑,平衡完成。否则继续按这几个步骤判断处理。

2. 兄弟是黑色的,至少有一个孩子是红色的
            P.X                   A.X
            / \                   / \
          C.B  A.B      --->    P.B Y.B
               / \              / \
             X.X Y.R          C.B X.X
   则把A染成父节点的颜色,把父节点染成黑色,把A的红色孩子节点也染成黑色。
   然后进行一次左/右旋。由于C子树比A子树少一层黑色,因此C和X子树的黑色是
   相等的(A是黑色),因此C和X已经平衡了。另外Y的子树(不包含Y)和C/X的黑
   色是一样多的,因此P和Y的黑色也是相等的。这样整棵树就平衡了(P下的黑色
   应该是C+1,现在达到了)

2. 兄弟是红色
            P.B                   A.B
            / \                   / \
          C.B  A.R   --->       P.R  Y.B
               / \              / \
             X.B Y.B          C.B X.B
             
   由于A子树的黑色比C子树多一层,因此X, Y肯定不是哨兵节点。这时候需要染
   色旋转。可以判断旋转之后X, Y的黑平衡依然符合要求,只需要解决C的黑平衡
   即可。这种情况就转换成了情况1/2
*/
rbnode_t *rbtree_del(rbtree_t *tree, void* key)
{
    rbnode_t **path[RB_TREE_MAX_DEPTH];
    rbnode_t *delnode = NULL;
    rbnode_t *subnode = NULL;
    rbnode_t *rmnode;
    rbnode_t *A;
    rbnode_t *P;
    rbnode_t *C;
    int      depth = 0;
    int      fdepth;
    int      ret = -1;
    unsigned char lr;

    /* 查找树删除 */
    path[depth] = &tree->tree;
    while (!RB_TREE_IS_NIL(*path[depth])){
        delnode=*path[depth];
        ret = tree->cmp(delnode, key);
        if (ret > 0) {
            path[++depth] = &delnode->child[RB_TREE_LR_RIGHT];
        } else if (ret < 0) {
            path[++depth] = &delnode->child[RB_TREE_LR_LEFT];
        } else {
            break;
        }
    }
    fdepth = depth;
    rmnode = delnode;

    if (0 != ret) {
        return NULL;
    } else if (RB_TREE_IS_NIL(delnode->child[RB_TREE_LR_LEFT])) {
        subnode = delnode->child[RB_TREE_LR_RIGHT];
        subnode->lr = rmnode->lr;
    } else if (RB_TREE_IS_NIL(delnode->child[RB_TREE_LR_RIGHT])) {
        subnode = delnode->child[RB_TREE_LR_LEFT];
        subnode->lr = rmnode->lr;
    } else {
        path[++depth] = &delnode->child[RB_TREE_LR_RIGHT];
        rmnode = delnode->child[RB_TREE_LR_RIGHT];
        while (!(RB_TREE_IS_NIL(rmnode->child[RB_TREE_LR_LEFT]))) {
            path[++depth] = &rmnode->child[RB_TREE_LR_LEFT];
            rmnode = rmnode->child[RB_TREE_LR_LEFT];
        }
        subnode = rmnode->child[RB_TREE_LR_RIGHT];
        
        /*replace the delnode*/
        rmnode->child[RB_TREE_LR_LEFT] = delnode->child[RB_TREE_LR_LEFT];
        rmnode->child[RB_TREE_LR_RIGHT] = delnode->child[RB_TREE_LR_RIGHT];
        subnode->lr = rmnode->lr;
        rmnode->lr = delnode->lr;
        rmnode->color = delnode->color;
        *path[fdepth] = rmnode;
        path[fdepth+1] = &rmnode->child[RB_TREE_LR_RIGHT]; //delnode will delete
    }
    *path[depth] = subnode;
    
    if (RB_TREE_IS_RED(rmnode)) {
        return delnode;
    }

    while (depth > 0) {
        if (RB_TREE_IS_RED(*path[depth])) {
            RB_TREE_SET_BLACK(*path[depth]);
            break;
        }
        C = *path[depth];
        P = *path[depth-1];
        A = P->child[RB_TREE_LR_OTHER(C)];
        
        if (RB_TREE_IS_RED(A)) {
            /*
              2. 兄弟是红色
                  P.B               A.B        P.B               A.B
                  / \               / \        / \               / \
                C.B  A.R   --->  P.R  Y.B    A.R  C.B   --->   Y.B  P.R
                     / \         / \         / \                    / \
                   X.B Y.B     C.B X.B     Y.B X.B                X.B C.B 
            */
            rbnode_t *X = A->child[RB_TREE_LR_INDEX(C)];
            rbnode_t *Y = A->child[RB_TREE_LR_OTHER(C)];
            lr = RB_TREE_LR_INDEX(C);

            path[depth+1] = path[depth];
            path[depth] = &A->child[RB_TREE_LR_INDEX(C)];

            *path[depth-1] = A; A->lr=P->lr;
            RB_TREE_SET_CHILD(A, lr, P);
            RB_TREE_SET_CHILD(P, RB_TREE_LR_REVERSE(lr), X);
            
            RB_TREE_SET_RED(P);
            RB_TREE_SET_BLACK(A);

            ++depth;
            A = X;
        }
        
        if (RB_TREE_IS_BLACK(A->child[RB_TREE_LR_LEFT]) && RB_TREE_IS_BLACK(A->child[RB_TREE_LR_RIGHT])) {
            /*
                P.X                   P.X
                / \                   / \
              C.B  A.B      --->    C.B  A.R
                   / \                   / \
                 X.B Y.B               X.B Y.B
            */
            RB_TREE_SET_RED(A);
            --depth;
        } else if (RB_TREE_IS_RED(A->child[RB_TREE_LR_INDEX(C)])) {// 近侄优先于远侄
            /*
                P.X              X.X                 P.X              X.X
                / \            /     \               / \            /     \
              C.B  A.B  ---> P.B     A.B          A.B  C.B  --->  A.B     P.B
                   / \       / \     / \          / \             / \     / \
                 X.R Y.X   C.B M.B N.B Y.X     Y.X X.R          Y.X N.B M.B C.B
                 / \                               / \
               M.B N.B                           N.B M.B
            */
            rbnode_t *X = A->child[RB_TREE_LR_INDEX(C)];
            rbnode_t *Y = A->child[RB_TREE_LR_OTHER(C)];
            rbnode_t *M = X->child[RB_TREE_LR_INDEX(C)];
            rbnode_t *N = X->child[RB_TREE_LR_OTHER(C)];
            lr = RB_TREE_LR_INDEX(C);

            *path[depth-1] = X; X->lr=P->lr;
            RB_TREE_SET_CHILD(A, lr, N);   // A->N
            RB_TREE_SET_CHILD(X, lr, P);   // X->P
            RB_TREE_SET_CHILD(X, RB_TREE_LR_REVERSE(lr), A);   // X->A
            RB_TREE_SET_CHILD(P, RB_TREE_LR_REVERSE(lr), M);   // P->M

            X->color = P->color;
            RB_TREE_SET_BLACK(P);
            break;
        } else { //远侄 
            /*
                P.X            A.X          P.X            A.X
                / \            / \          / \            / \
              C.B  A.B  ---> P.B Y.B      A.B  C.B  ---> Y.B P.B
                   / \       / \          / \                / \
                 X.X Y.R   C.B X.X      Y.R X.X            X.X C.B
            */
            rbnode_t *X = A->child[RB_TREE_LR_INDEX(C)];
            rbnode_t *Y = A->child[RB_TREE_LR_OTHER(C)];

            *path[depth-1] = A; A->lr=P->lr;
            RB_TREE_SET_CHILD(A, RB_TREE_LR_INDEX(C), P);   // A->P
            RB_TREE_SET_CHILD(P, RB_TREE_LR_OTHER(C), X);   // P->X

            RB_TREE_SET_COLOR(A, P->color);
            RB_TREE_SET_BLACK(P);
            break;
        }
    }
    RB_TREE_SET_BLACK(*path[0]);
    
    return delnode;
}

rbnode_t *rbtree_get(rbtree_t *tree, void* key)
{
    rbnode_t *node = tree->tree;
    int ret;

    while (!RB_TREE_IS_NIL(node)) {
        ret = tree->cmp(node, key);
        if (0 == ret) {
            return node;
        } else if (0 < ret) {
            node = node->child[RB_TREE_LR_RIGHT];
        } else {
            node = node->child[RB_TREE_LR_LEFT];
        }
    }

    return NULL;
}

int rbtree_walk(rbtree_t *tree, rbwalk pcb, void *pcbarg, RBORDER_E order)
{
    switch (order) {
      case RB_TREE_ORDER_PRE:
        return _rb_walk_pre(tree->tree, pcb, pcbarg);
      case RB_TREE_ORDER_IN:
        return _rb_walk_in(tree->tree, pcb, pcbarg);
      case RB_TREE_ORDER_POST:
      default:
        return _rb_walk_post(tree->tree, pcb, pcbarg);
    }
}


void rbtree_destroy(rbtree_t *tree, rbdestroy pcb, void *pcbarg, RBORDER_E order)
{
    switch (order) {
      case RB_TREE_ORDER_PRE:
        _rb_destroy_pre(tree->tree, pcb, pcbarg);
        break;
      case RB_TREE_ORDER_IN:
        _rb_destroy_in(tree->tree, pcb, pcbarg);
        break;
      case RB_TREE_ORDER_POST:
      default:
        _rb_destroy_post(tree->tree, pcb, pcbarg);
        break;
    }

    tree->tree = &tree->nil;
}

#ifdef RBTREE_TEST

typedef struct
{
    rbnode_t node;
    int key;
}rbtree_test_t;

static char* printcb(rbnode_t *node, void *arg)
{
    static char buf[64];
    static char COLOR[2] = {'R', 'B'};
    rbtree_test_t *t = (rbtree_test_t*)node;

    sprintf(buf, "%d.%c", t->key, COLOR[node->color]);

    return buf;
}

static void _printtree(rbnode_t *node, int iDepth, int *piHaveY, FILE *fp, rbtreeprintcb pcb, void *pcbarg)
{
    int i;

    for (i=0; i<iDepth; ++i) {
        if (piHaveY[i] != 0) {
            fprintf(fp, "%s", "│  ");
        } else {
            fprintf(fp, "%s", "    ");
        }
    }

    if (iDepth > 0) {
        if (node->lr==RB_TREE_LR_LEFT || RB_TREE_IS_NIL(node)) {
            fprintf(fp, "%s", "└─");
        } else {
            fprintf(fp, "%s", "├─");
        }
    } else {
        fprintf(fp, "  ");
    }

    if (RB_TREE_IS_NIL(node)) {
        fprintf(fp, "%s", "NIL\r\n");
        return;
    } else {
        fprintf(fp, "%s\r\n", pcb(node, pcbarg));
        if (node->lr==RB_TREE_LR_LEFT) {
            piHaveY[iDepth] = 0;
        }
    }
    piHaveY[iDepth+1] = 1;

    _printtree(node->child[RB_TREE_LR_RIGHT], iDepth+1, piHaveY, fp, pcb, pcbarg);
    _printtree(node->child[RB_TREE_LR_LEFT], iDepth+1, piHaveY, fp, pcb, pcbarg);
}

void rbtree_print(rbtree_t *tree, FILE *fp, rbtreeprintcb pcb, void *pcbarg)
{
    int Y[RB_TREE_MAX_DEPTH] = {0};
    _printtree(tree->tree, 0, Y, fp, pcb, pcbarg);
}

static int cmp(rbnode_t *node, void* key)
{
    return (int)key - ((rbtree_test_t*)node)->key;
}

static int walkcb(rbnode_t *node, void *arg)
{
    rbtree_test_t *t = (rbtree_test_t*)node;
    printf("%d ", t->key);
    return 0;
}

static void destroycb(rbnode_t *node, void *arg)
{
    rbtree_test_t *t = (rbtree_test_t*)node;
    printf("%d ", t->key);
    node->child[0] = node->child[1] = NULL;
}

int main(int argc, char *argv[])
{
    rbtree_t tree;
    rbtree_test_t nodes[16];
    int i;

    rbtree_init(&tree, cmp);

    for (i=0; i<15; ++i) {
        nodes[i].key = 1*(i+1);
        rbtree_add(&tree, &nodes[i].node, (void*)(nodes[i].key));
    }
    rbtree_print(&tree, stdout, printcb, NULL);
    /*nodes[i].key = 8;
    for (i=15; i>1; --i) {
        rbtree_del(&tree, (void*)i);
    }
    rbtree_del(&tree, (void*)i);
    //rbtree_del(&tree, 15);
    rbtree_print(&tree, stdout, printcb, NULL);*/
    //rbtree_walk(&tree, walkcb, NULL, RB_TREE_ORDER_PRE);printf("\n");
    //rbtree_walk(&tree, walkcb, NULL, RB_TREE_ORDER_IN);printf("\n");
    //rbtree_walk(&tree, walkcb, NULL, RB_TREE_ORDER_POST);printf("\n");
    rbtree_destroy(&tree, destroycb, NULL, RB_TREE_ORDER_POST);printf("\n");

    return 0;
}

#endif

#ifdef __cplusplus
}
#endif




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值