RBTree(红黑树的简单实现)

来源:互联网 发布:一键装修淘宝店铺软件 编辑:程序博客网 时间:2024/06/06 16:39
//在Linux下使用dot工具进行红黑树打印
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdbool.h>#define RB_RED 1#define RB_BLACK 0typedef 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;}