C红黑树统计英文单词数量

来源:互联网 发布:泰豪软件 编辑:程序博客网 时间:2024/05/01 22:09
#include <stdio.h>#include <stdlib.h>#include <string.h>#define SUCCESS 0#define ERROR -1#define RB_DEFAULT_VALUE 0#define rb_keycmp strcmp#define rb_keydup strdup//to do: 中序和后序非递归遍历,求树的深度,typedef enum {    BLACK, RED} rb_color;typedef char* rb_key;typedef size_t rb_value;typedef struct rb_node {    rb_color color;    struct rb_node *p;    struct rb_node *left;    struct rb_node *right;    rb_key key;    rb_value value;} rb_node;typedef struct rbtree {    rb_node *root;    rb_node *nil;    size_t size;} rbtree;typedef struct {    rb_key key;    rb_value value;} key_value;rb_node *rb_create_node(void) ;//堆上新建结点void *rb_free_node(rb_node *nd) ;//清除结点nd.rbtree *rb_create_tree(void) ;//堆上新建树void rb_free_tree(rbtree *tr) ;//清除树trrb_node *rb_search(rbtree *tr, rb_key z) ;//根据key查找结点,找到返回指针,找不到则返回NULLvoid rb_insert(rbtree *tr, rb_node *z) ;//将z结点插入树int rb_update(rbtree *tr, rb_key key, rb_value value) ; //用value更新key结点的值,找不到结点则返回异常值-1;void rb_delete(rbtree *tr, rb_node *z) ; //删除z结点.rb_node *rb_minimum(rbtree *tr, rb_node* x) ; //tr树x子树的最小结点rb_node *rb_maximum(rbtree *tr, rb_node* x) ; //tr树x子树的最大结点int rb_force_update(rbtree *tr, rb_key key, rb_value value) ;//用value更新或强制建立key结点的值,找不到结点则新建结点再更新;rb_node *rb_force_search(rbtree *tr, rb_key key) ;//根据key强制返回结点(找不到就在堆上新建结点key再返回)key_value *rb_flatten(rbtree *tr) ;//抽取树的键值,按前序遍历的方式将树"扁平化"void rb_graph(rbtree *tr, rb_node *x, char *prefix) ; //打印红黑树的直观图形static void print_by_key_asce(rbtree *tr, rb_node *nd) ; //按key升序遍历打印tr从nd开始的所有键值static void print_by_value_desc(rbtree *tr) ; //按value降序打印所有键值static void test_leak(void); //测试内存泄露static void _rb_free_tree(rbtree *tr, rb_node *nd) ;//辅助函数static void left_rotate(rbtree *tr, rb_node *x) ;//辅助函数static void right_rotate(rbtree *tr, rb_node *x) ;//辅助函数static void rb_transplant(rbtree *tr, rb_node *u, rb_node *v) ;//辅助函数static void rb_insert_fixup(rbtree *tr, rb_node *z) ;//辅助函数static void rb_delete_fixup(rbtree *tr, rb_node *x) ;//辅助函数static int rb_cmp(const void *a, const void *b) ;//用于qsort的辅助函数int main(void) {    rbtree *tr = rb_create_tree();    char wd[100];    rb_node *nd;    while (scanf("%s\n", wd) == 1) {        nd = rb_force_search(tr, wd);        nd->value += 1;    }    print_by_value_desc(tr);    nd=tr->root;    printf("root is %s\n",nd->key);    while (nd!=tr->nil) {        rb_delete(tr, nd);        nd=tr->root;    }    printf("after all deleted, tree is like:\n");    print_by_value_desc(tr);    rb_free_tree(tr);    return SUCCESS;}static void test_leak(void) {    int i;    rb_node *nd;    rbtree *tr = rb_create_tree();    char *keys[]= {"ab","c","de","c","ab","e","c","ee","e"};    for (i=0; i<9; i++) {        nd = rb_force_search(tr, keys[i]);        nd->value += 1;    }    print_by_value_desc(tr);    rb_free_tree(tr);}rb_node *rb_create_node(void) {    rb_node *nd = (rb_node *) malloc(sizeof(rb_node));    if (nd == NULL)        return NULL;    nd->color = BLACK;    nd->p = NULL;    nd->left = NULL;    nd->right = NULL;    nd->key = NULL;    nd->value = RB_DEFAULT_VALUE;    return nd;}void *rb_free_node(rb_node *nd) {    free(nd->key);    free(nd);    return SUCCESS;}rbtree *rb_create_tree(void) {    rbtree *tr = (rbtree *) malloc(sizeof(rbtree));    if (tr == NULL)        return NULL;    rb_node *nil = rb_create_node();    if (nil == NULL)        return NULL;    tr->nil = nil;    tr->root = nil;    tr->size = 0;    return tr;}static void _rb_free_tree(rbtree *tr, rb_node *nd) {    if (nd != tr->nil) {        _rb_free_tree(tr, nd->left);        _rb_free_tree(tr, nd->right);        free(nd->key);        free(nd);    }}void rb_free_tree(rbtree *tr) {    _rb_free_tree(tr, tr->root);    free(tr->nil);    free(tr);}static void left_rotate(rbtree *tr, rb_node *x) {    rb_node *y = x->right;    x->right = y->left;    if (y->left != tr->nil)        y->left->p = x;    y->p = x->p;    if (x == tr->root)        tr->root = y;    else if ( x == x->p->left)        x->p->left = y;    else        x->p->right = y;    y->left = x;    x->p = y;}static void right_rotate(rbtree *tr, rb_node *x) {    rb_node *y = x->left;    x->left = y->right;    if (y->right != tr->nil)        y->right->p = x;    y->p = x->p;    if (x == tr->root)        tr->root = y;    else if ( x == x->p->right )        x->p->right = y;    else        x->p->left = y;    y->right = x;    x->p = y;}rb_node *rb_search(rbtree *tr, rb_key key) {    rb_node *x = tr->root;    int r;    while (x != tr->nil) {        r = rb_keycmp(key, x->key);        if (r == 0)            return x;        else if (r < 0)            x = x->left;        else            x = x->right;    }    return NULL;}void rb_insert(rbtree *tr, rb_node *z) {    rb_node *y = tr->nil;    rb_node *x = tr->root;    while (x != tr->nil) {        y = x;        if (rb_keycmp(z->key, x->key) < 0)            x = x->left;        else            x = x->right;    }    z->p = y;    if (y == tr->nil)        tr->root = z;    else if (rb_keycmp(z->key, y->key) < 0)        y->left = z;    else        y->right = z;    z->left = tr->nil;    z->right = tr->nil;    z->color = RED;    rb_insert_fixup(tr, z);    tr->size++;}static void rb_insert_fixup(rbtree *tr, rb_node *z) {    rb_node *y;    while (z->p->color == RED) {        if (z->p == z->p->p->left) {            y = z->p->p->right;            if (y->color == RED) {                z->p->color = BLACK;                y->color = BLACK;                z->p->p->color = RED;                z = z->p->p;            } else {                if (z == z->p->right) {                    z = z->p;                    left_rotate(tr, z);                }                z->p->color = BLACK;                z->p->p->color = RED;                right_rotate(tr, z->p->p);            }        } else {            y = z->p->p->left;            if (y->color == RED) {                z->p->color = BLACK;                y->color = BLACK;                z->p->p->color = RED;                z = z->p->p;            } else {                if (z == z->p->left) {                    z = z->p;                    right_rotate(tr, z);                }                z->p->color = BLACK;                z->p->p->color = RED;                left_rotate(tr, z->p->p);            }        }    }    tr->root->color = BLACK;}rb_node *rb_force_search(rbtree *tr, rb_key key) {    rb_node *y = tr->nil;    rb_node *x = tr->root;    int r;    while (x != tr->nil) {        r = rb_keycmp(key, x->key);        if (r == 0)            return x;        y = x;        if (r < 0)            x = x->left;        else            x = x->right;    }    rb_node *z = rb_create_node();    rb_node *original_z = z;    if (z == NULL)        return NULL;    if ((z->key = rb_keydup(key)) == NULL)        return NULL;    z->p = y;    if (y == tr->nil)        tr->root = z;    else if (rb_keycmp(z->key, y->key) < 0)        y->left = z;    else        y->right = z;    z->left = tr->nil;    z->right = tr->nil;    z->color = RED;    rb_insert_fixup(tr, z);    tr->size++;    return original_z;}int rb_update(rbtree *tr, rb_key key, rb_value value) {    rb_node* nd = rb_search(tr, key);    if (nd == NULL)        return ERROR;    nd->value = value;    return SUCCESS;}int rb_force_update(rbtree *tr, rb_key key, rb_value value) {    rb_node* nd = rb_force_search(tr, key);    if (nd == NULL)        return ERROR;    nd->value = value;    return SUCCESS;}static void rb_transplant(rbtree *tr, rb_node *u, rb_node *v) {    if (u->p == tr->nil)        tr->root = v;    else if (u == u->p->left)        u->p->left = v;    else        u->p->right = v;    v->p = u->p;}rb_node *rb_minimum(rbtree *tr, rb_node* x) {    while (x->left != tr->nil)        x = x->left;    return x;}rb_node *rb_maximum(rbtree *tr, rb_node* x) {    while (x->right != tr->nil)        x = x->right;    return x;}void rb_delete(rbtree *tr, rb_node *z) {    rb_node *y = z;    rb_color y_original_color = y->color;    rb_node *x;    if (z->left == tr->nil) {        x = z->right;        rb_transplant(tr, z, z->right);    } else if (z->right == tr->nil) {        x = z->left;        rb_transplant(tr, z, z->left);    } else {        y = rb_minimum(tr, z->right);        y_original_color = y->color;        x = y->right;        if (y->p == z)            x->p = y;        else {            rb_transplant(tr, y, y->right);            y->right = z->right;            y->right->p = y;        }        rb_transplant(tr, z, y);        y->left = z->left;        y->left->p = y;        y->color = z->color;    }    if (y_original_color == BLACK)        rb_delete_fixup(tr, x);    rb_free_node(z);    tr->size--;}static void rb_delete_fixup(rbtree *tr, rb_node *x) {    while (x != tr->root && x->color == BLACK) {        rb_node *w;        if (x == x->p->left) {            w = x->p->right;            if (w->color == RED) {                w->color = BLACK;                x->p->color = RED;                left_rotate(tr, x->p);                w = x->p->right;            }            if (w->left->color == BLACK && w->right->color == BLACK) {                w->color = RED;                x = x->p;            } else {                if (w->right->color == BLACK) {                    w->left->color = BLACK;                    w->color = RED;                    right_rotate(tr, w);                    w = x->p->right;                }                w->color = x->p->color;                w->p->color = BLACK;                w->right->color = BLACK;                left_rotate(tr, x->p);                x = tr->root;            }        } else {            w = x->p->left;            if (w->color == RED) {                w->color = BLACK;                x->p->color = RED;                right_rotate(tr, x->p);                w = x->p->left;            }            if (w->right->color == BLACK && w->left->color == BLACK) {                w->color = RED;                x = x->p;            } else {                if (w->left->color == BLACK) {                    w->right->color = BLACK;                    w->color = RED;                    left_rotate(tr, w);                    w = x->p->left;                }                w->color = x->p->color;                w->p->color = BLACK;                w->left->color = BLACK;                right_rotate(tr, x->p);                x = tr->root;            }        }    }    x->color = BLACK;}#define LEF "└───"#define RIG "┌───"#define IND1 "    "#define IND2 "│   "void rb_graph(rbtree *tr, rb_node *x, char *prefix) {    if (x != tr->nil) {        rb_node *p = x->p;        char *last_prefix;        if (p != tr->nil) {            rb_node *print_by_key_asce = p->p;            if (p->left == x)                last_prefix = LEF;            else                last_prefix = RIG;            if (print_by_key_asce != tr->nil) {                if ((print_by_key_asce->left == p) == (p->left == x))                    prefix = strcat(prefix, IND1);                else                    prefix = strcat(prefix, IND2);            }        }        rb_graph(tr, x->right, prefix);        printf("%s%s%s[%d]%lu\n", prefix, last_prefix, x->key, x->color,               x->value);        rb_graph(tr, x->left, prefix);    }}key_value *rb_flatten(rbtree *tr) {    int i = 0, top = 0;    key_value *kvl = (key_value*) malloc(tr->size * sizeof(key_value));    rb_node *nds[tr->size];    nds[top] = tr->root;    rb_node *nd;    while (top >= 0) {        nd = nds[top--];        if (nd != tr->nil) {            kvl[i].key = nd->key;            kvl[i].value = nd->value;            i++;            nds[++top] = nd->left;            nds[++top] = nd->right;        }    }    return kvl;}static int rb_cmp(const void *a, const void *b) {    return (*(key_value *) a).value > (*(key_value *) b).value ? -1 : 1;}static void print_by_key_asce(rbtree *tr, rb_node *nd) {    if (nd != tr->nil) {        print_by_key_asce(tr, nd->left);        printf("%s\t%lu\n", nd->key, nd->value);        print_by_key_asce(tr, nd->right);    }}static void print_by_value_desc(rbtree *tr) {    key_value *kvl = rb_flatten(tr);    size_t rb_size = tr->size;    qsort(kvl, rb_size, sizeof(kvl[0]), rb_cmp);    size_t i = 0;    for (; i < rb_size; i++) {        printf("%s\t%lu\n", kvl[i].key, kvl[i].value);    }    free(kvl);}

0 0
原创粉丝点击