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

4 篇文章 0 订阅
#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) ;//清除树tr
rb_node *rb_search(rbtree *tr, rb_key z) ;//根据key查找结点,找到返回指针,找不到则返回NULL
void 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值