RBTree(红黑树的简单实现)

//在Linux下使用dot工具进行红黑树打印
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#define RB_RED 1
#define RB_BLACK 0

typedef struct rbtree_node_t{
    struct rbtree_node_t *parent;
    struct rbtree_node_t *left;
    struct rbtree_node_t *right;
    int value;
    int color;
} rbtree_node_t;

typedef struct rbtree_t{
    rbtree_node_t* root;
} rbtree_t;

void rbtree_rotate_left(rbtree_t*tree, rbtree_node_t* node){
    rbtree_node_t *n1 = node;
    rbtree_node_t* n0 = n1->parent;
    rbtree_node_t *n3 = n1->right;
    rbtree_node_t *n4 = n3->left;

    n1->right = n4;
    if(n4)
        n4->parent = n1;

    n3->left = n1;
    n1->parent = n3;

    n3->parent = n0;
    if(n0){
        if(n0->left == n1) n0->left = n3;
        else n0->right = n3;
    }
    else{
        tree->root = n3;
    }
}

void rbtree_rotate_right(rbtree_t* tree, rbtree_node_t* node){
    rbtree_node_t *n1 = node;
    rbtree_node_t* n0 = n1->parent;
    rbtree_node_t *n3 = n1->left;
    rbtree_node_t *n4 = n3->right;

    n1->left = n4;
    if(n4)
        n4->parent = n1;

    n3->right = n1;
    n1->parent = n3;

    n3->parent = n0;
    if(n0){
        if(n0->right == n1) n0->right = n3;
        else n0->left = n3;
    }
    else{
        tree->root = n3;
    }
}

void rbtree_init(rbtree_t* tree){
    tree->root = NULL;
}

void rbtree_node_init(rbtree_node_t* node){
    node->parent = node->left = node->right = NULL;
    node->color = RB_RED;
}

int rbtree_red_node(rbtree_node_t *node){
    return node && node->color == RB_RED;
}

int rbtree_black_node(rbtree_node_t* node){
    return node && node->color == RB_BLACK;
}

bool rbtree_insert_node(rbtree_t* tree, rbtree_node_t*node){
    rbtree_node_t *parent = tree->root;
    while(true){
        if(parent->value > node->value){
            if(parent->left == NULL){
                parent->left = node;
                node->parent = parent;
                return true;
            }
            parent = parent->left;
        }
        else if(parent->value < node->value){
            if(parent->right == NULL){
                parent->right = node;
                node->parent = parent;
                return true;
            }
            parent = parent->right;
        }
        else{
            free(node);
            return false;
        }
    }
}

bool rbtree_insert_check(rbtree_t *tree, rbtree_node_t *node){
    if(node->parent == NULL){
        node->color = RB_BLACK;
        return true;
    }
    //one, parent black,dont change
    if(node->parent->color == RB_BLACK){
        return true;
    }

    //two, parent is red
    //uncle is red
    rbtree_node_t* parent = node->parent;
    rbtree_node_t *gparent = parent->parent;
    rbtree_node_t *uncle = NULL; 
    if(parent == gparent->right){
        uncle = gparent->left;
    }
    else{
        uncle = gparent->right;
    }
    
    if(rbtree_red_node(uncle)){
        parent->color = RB_BLACK;
        uncle->color = RB_BLACK;
        gparent->color = RB_RED;
        rbtree_insert_check(tree, gparent);
        return true;
    }

    //uncle is black
    //gparent parent new node in line;
    if(node == parent->right && parent == gparent->right){
        rbtree_rotate_left(tree, gparent);
        parent->color = RB_BLACK;
        gparent->color = RB_RED;
        return true;
    }
    else if(node == parent->left && parent == gparent->left){
        rbtree_rotate_right(tree, gparent);
        parent->color = RB_BLACK;
        gparent->color = RB_RED;
        return true;
    }

    // notin line
    if(node == parent->right){ //parent is gparent left son
      rbtree_rotate_left(tree, parent);
      rbtree_insert_check(tree, parent); 
      return true;
    }
    else{//node is left child, parent is right child
        rbtree_rotate_right(tree, parent);
        rbtree_insert_check(tree, parent);
        return true;
    } 

}

void rbtree_insert(rbtree_t* tree, int value){
    rbtree_node_t *node = malloc(sizeof(rbtree_node_t));
    rbtree_node_init(node);
    node->value = value;

    if(tree->root == NULL){
        tree->root = node;
        node->color = RB_BLACK;
        return;
    }
    //if root != NULL so first insert , dont care color:
    if(rbtree_insert_node(tree, node)){
    //check new node is bad rbtree 
        rbtree_insert_check(tree, node);
    }

}

void rbtree_print_node(FILE*fp, rbtree_node_t* node){
    if(node == NULL)
        return;
    const char *color = node->color == RB_RED?"red":"black";
    fprintf(fp, "node[shape=record,style=filled,color=%s,fontcolor=white]; %d[label=\"<f0>|<f1> %d|<f2>\"];\n",color, node->value,node->value);
    if(node->parent){
        if(node == node->parent->left)
            fprintf(fp, "%d:f0:sw->%d:f1;\n", node->parent->value, node->value);
        else{
            fprintf(fp, "%d:f2:se->%d:f1;\n", node->parent->value, node->value);
        }
    }
    rbtree_print_node(fp, node->left);
    rbtree_print_node(fp, node->right);
}

void rbtree_print(rbtree_t* tree, const char *filename){
    if(tree->root == NULL)
        return;
    FILE* fp = fopen(filename, "w");
    fprintf(fp, "digraph G{\n");

    rbtree_print_node(fp, tree->root);
    fprintf(fp,"}\n");

    fclose(fp);
    char cmd[1024];
    sprintf(cmd, "dot %s -Tpng -o %s.png", filename,filename);
    printf("cmd:%s\n",cmd);
    popen(cmd,"r");
}


int main()
{
    rbtree_t tree;
    rbtree_init(&tree);

    rbtree_insert(&tree, 100);
    rbtree_insert(&tree, 99);
    rbtree_insert(&tree, 98);
    rbtree_insert(&tree, 97);
    rbtree_insert(&tree, 96);
    rbtree_insert(&tree, 95);
    rbtree_insert(&tree, 94);
    rbtree_insert(&tree, 93);

    rbtree_print(&tree,"0.dot");

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值