红黑树纯C语言实现,参考算法导论,已验证

3 篇文章 0 订阅
1 篇文章 0 订阅

说起红黑树,最头疼的就是插入或删除后引起的不平衡,各种旋转,着色细节让人难以理解。我一开始是网上找别人的代码来看,看的一头雾水,还是算法导论上的的伪代码到位,不用纠结于各种细节,虽然我现在依然没有彻底搞清楚,但是根据书上的伪代码写了一遍,居然也能通过验证。

这里不做深入分析,只要对红黑树有个大概的了解,相信书上的算法就好。对插入和删除要做哪些事情大体了解下,不用探究细节。不废话,直接上代码,我的一些理解写在了代码注释中

更新一下,删除节点在remove_rbt_node方法末尾,在执行待删除节点与他右子树最左边的节点交换后,调用free,这点算法导论书上没有写出

调试中输出了涉及旋转、交换的节点的值,直观的感受插入和删除操作的过程

头文件

/* 
 * File:   rb_tree.h
 * Author: weng
 *
 * Created on 2018年11月8日, 下午9:40
 */

#ifndef RB_TREE_H
#define RB_TREE_H

#ifdef __cplusplus
extern "C" {
#endif

#define DEBUG_RBT 1

    typedef int RBTKey;

    enum rbt_color {
        RED = 0, BLACK
    };

    struct rbt_node {
        struct rbt_node* parent;
        struct rbt_node* left;
        struct rbt_node* right;
        RBTKey key;
        enum rbt_color color;
    };

    struct rb_tree {
        struct rbt_node* root;
        struct rbt_node* nil;
    };

    typedef struct rbt_node RBTNode;
    typedef struct rb_tree RBTree;

    /*
     * 常用方法
     */
    RBTree* create_rbtree(void); //使用malloc在堆中创建红黑树并初始化
    RBTree* init_rbtree(RBTree* t); //初始化
    RBTree* insert_rbt_node(RBTree* t, const RBTKey key); //插入key
    RBTree* remove_rbt_node(RBTree* t, const RBTKey key); //删除key对应节点
    void clear_rbtree(RBTree* t); //后序遍历,free树中的节点,对于t需要另行处理
    void display_rbt(RBTree* t); //中序遍历
    void display_rbt_prevorder(RBTree* t); //先序遍历
    void display_rbt_postorder(RBTree* t); //后序遍历
    void show_rbt(RBTree* t); //图示




    /*
     * 辅助函数
     * 参数中RBTree* t, RBTNode* r
     * t->root为根节点, r为待操作的节点
     */
    RBTNode* create_rbt_node(const RBTKey key); //使用malloc在堆中创建节点并初始化

    RBTree* rbt_insert_fixup(RBTree* t, RBTNode* r); //插入后平衡

    RBTree* rbt_left_rotate(RBTree* t, RBTNode* r); //左旋
    RBTree* rbt_right_rotate(RBTree* t, RBTNode* r); //右旋

    RBTree* rbt_transplant(RBTree* t, RBTNode* u, RBTNode* v); //互换节点
    RBTree* rbt_delete_fixup(RBTree* t, RBTNode* r); //删除后平衡
    RBTNode* rbt_minimum(RBTree* t, RBTNode* r); //返回将与待删除节点互换的节点 \
    //这里是用待删除节点的右孩子的最左边一个节点与待删除节点互换,使得他们位置变换, \
    //然后执行删除,这样树的整体结构不变,之后执行平衡策略

    void clear_rbt_node_post(RBTree* t, RBTNode* r);

    void display_rbt_node(RBTree* t, RBTNode* r);
    void display_rbt_node_prev(RBTree* t, RBTNode* r);
    void display_rbt_node_post(RBTree* t, RBTNode* r);
    void show_rbt_node(RBTree* t, RBTNode* r, int high, int n); //



#ifdef __cplusplus
}
#endif

#endif /* RB_TREE_H */

方法实现源文件

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
#include "rb_tree.h"
#include <stdio.h>
#include <stdlib.h>

RBTree* create_rbtree(void) {
    RBTree* t = (RBTree*) malloc(sizeof (RBTree));
    /*
        t->nil = create_rbt_node(0);
        t->nil->color = BLACK;
        t->root = t->nil;
        return t;
     */
    init_rbtree(t);
    return t;
}

RBTree* init_rbtree(RBTree* t) {
    t->nil = create_rbt_node(0);
    t->nil->color = BLACK;
    t->root = t->nil;
    return t;
}

RBTree* insert_rbt_node(RBTree* t, const RBTKey key) {
    RBTNode* rp = t->root; //插入路径上的迭代器//书上记作x
    RBTNode* parent = t->nil; //迭代器的父节点//y
    /*
        RBTNode* r = create_rbt_node(key); //待插入的节点//z
     */
    while (rp != t->nil) {
        parent = rp;
        if (key < rp->key)
            rp = rp->left;
        else if (key > rp->key)
            rp = rp->right;
        else
            return t; //树中已有key,返回
    }

    RBTNode* r = create_rbt_node(key); //待插入的节点//z
    r->parent = parent;
    r->left = t->nil;
    r->right = t->nil;

    if (parent == t->nil)
        t->root = r;
    else if (key < parent->key)
        parent->left = r;
    else
        parent->right = r;

    t = rbt_insert_fixup(t, r);
    return t;
}

RBTree* remove_rbt_node(RBTree* t, const RBTKey key) {
    RBTNode* rp = t->root; //删除路径上的迭代器//y
    while (rp != t->nil) {
        if (key < rp->key)
            rp = rp->left;
        else if (key > rp->key)
            rp = rp->right;
        else
            break; //找到key
    }
    if (rp == t->nil)
        return t; //未找到

    RBTNode* z = rp; //z 待删除key的节点
    enum rbt_color y_o_c = rp->color; //记录颜色
    RBTNode* x; //记录z的孩子节点

    if (z->left == t->nil) {
        x = z->right;
        rbt_transplant(t, z, z->right);
    } else if (z->right == t->nil) {
        x = z->left;
        rbt_transplant(t, z, z->left);
    } else {
        rp = rbt_minimum(t, z->right);

        /*
                //以下4行为tree_minimum方法
                rp = z->right;
                while (rp->left != t->nil) {
                    rp = rp->left;
                }
         */

        y_o_c = rp->color;
        x = rp->right;
        if (rp->parent == z)
            x->parent = rp;
        else {
            rbt_transplant(t, rp, rp->right);
            rp->right = z->right;
            rp->right->parent = rp;
        }
        rbt_transplant(t, z, rp);
        rp->left = z->left;
        rp->left->parent = rp;
        rp->color = z->color;
    }

#ifdef DEBUG_RBT
        printf("删除节点 %d\n", u->key);
#endif
    free(z);//删除节点

    if (y_o_c == BLACK)
        rbt_delete_fixup(t, x);
}

void clear_rbtree(RBTree* t) {
    if (t == NULL)return;
    clear_rbt_node_post(t, t->root);
    if (t->nil != NULL)
        free(t->nil);
}

void display_rbt(RBTree* t) {
    if (t == NULL)return;
    display_rbt_node(t, t->root);
    printf("\n");
}

void display_rbt_prevorder(RBTree* t) {
    if (t == NULL)return;
    display_rbt_node_prev(t, t->root);
    printf("\n");
}

void display_rbt_postorder(RBTree* t) {
    if (t == NULL)return;
    display_rbt_node_post(t, t->root);
    printf("\n");
}

void show_rbt(RBTree* t) {
    if (t == NULL)return;
    int h = 0;
    int n = 0;
    show_rbt_node(t, t->root, h, n);
}

RBTNode* create_rbt_node(const RBTKey key) {
    RBTNode* r = (RBTNode*) malloc(sizeof (RBTNode));
    r->left = r->right = r->parent = NULL;
    r->color = RED;
    r->key = key;
    return r;
}

/*
 * 参数中RBTree* t, RBTNode* r
 * t->root为根节点, r为待操作的节点
 */
RBTree* rbt_insert_fixup(RBTree* t, RBTNode* r) {
    while (r->parent->color == RED) {
        if (r->parent == r->parent->parent->left) {
            RBTNode* u = r->parent->parent->right; //r的叔叔uncle;//y
            if (u->color == RED) {//case 1
                r->parent->color = BLACK;
                u->color = BLACK;
                r->parent->parent->color = RED;
                r = r->parent->parent;
            } else if (r == r->parent->right) {//case 2
                r = r->parent;
                rbt_left_rotate(t, r);
            } else {//case 3//第三版书上这里没有else,加上
                r->parent->color = BLACK;
                r->parent->parent->color = RED;
                rbt_right_rotate(t, r->parent->parent);
            }
        } else {
            RBTNode* u = r->parent->parent->left; //r的叔叔uncle;//y
            if (u->color == RED) {
                r->parent->color = BLACK;
                u->color = BLACK;
                r->parent->parent->color = RED;
                r = r->parent->parent;
            } else if (r == r->parent->left) {
                r = r->parent;
                rbt_right_rotate(t, r);
            } else {//
                r->parent->color = BLACK;
                r->parent->parent->color = RED;
                rbt_left_rotate(t, r->parent->parent);
            }
        }
    }//while

    t->root->color = BLACK;
    return t;
}

RBTree* rbt_left_rotate(RBTree* t, RBTNode* r) {
    if (r->right != t->nil) {
        RBTNode* child = r->right; //y
#ifdef DEBUG_RBT
        printf("left_rolate %d<->%d\n", r->key, child->key);
#endif
        r->right = child->left;
        if (child->left != t->nil)
            child->left->parent = r;
        child->parent = r->parent;
        if (r->parent == t->nil)
            t->root = child;
        else if (r == r->parent->left)
            r->parent->left = child;
        else
            r->parent->right = child;
        child->left = r;
        r->parent = child;
    }

    return t;
}

RBTree* rbt_right_rotate(RBTree* t, RBTNode* r) {
    if (r->left != t->nil) {//书上伪代码之前假设这个条件,
        //根节点的父节点为nil已经在init_rbtree()方法中初始化
        RBTNode* child = r->left; //y
#ifdef DEBUG_RBT
        printf("right_rolate %d<->%d\n", r->key, child->key);
#endif
        r->left = child->right;
        if (child->right != t->nil)
            child->right->parent = r;
        child->parent = r->parent;
        if (r->parent == t->nil)
            t->root = child;
        else if (r == r->parent->right)
            r->parent->right = child;
        else
            r->parent->left = child;
        child->right = r;
        r->parent = child;
    }

    return t;
}

RBTree* rbt_transplant(RBTree* t, RBTNode* u, RBTNode* v) {
    if (u->parent == t->nil)
        t->root = v;
    else if (u == u->parent->left)
        u->parent->left = v;
    else
        u->parent->right = v;
    v->parent = u->parent;
#ifdef DEBUG_RBT
        printf("transplant %d %d\n", u->key, v->key);
#endif
    return t;
}

RBTree* rbt_delete_fixup(RBTree* t, RBTNode* x) {//r=x
    while (x != t->root && x->color == BLACK) {
        RBTNode* w; //记录x的兄弟节点
        if (x == x->parent->left) {
            w = x->parent->right;
            if (w->color == RED) {//case 1
                w->color = BLACK;
                x->parent->color = RED;
                rbt_left_rotate(t, x->parent);
                w = x->parent->right;
            }
            if (w->left->color == BLACK && w->right->color == BLACK) {//case 2
                w->color = RED;
                x = x->parent;
            } else if (w->right->color == BLACK) {//case 3
                w->left->color = BLACK;
                w->color = RED;
                rbt_right_rotate(t, w);
                w = x->parent->right;
            } else {//else一定要加上//case 4
                w->color = x->parent->color; //case 4
                x->parent->color = BLACK;
                w->right->color = BLACK;
                rbt_left_rotate(t, x->parent);
                x = t->root;
            }
        } else {//镜像
            w = x->parent->left;
            if (w->color == RED) {//case 1
                w->color = BLACK;
                x->parent->color = RED;
                rbt_right_rotate(t, x->parent);
                w = x->parent->left;
            }
            if (w->right->color == BLACK && w->left->color == BLACK) {//case 2
                w->color = RED;
                x = x->parent;
            } else if (w->left->color == BLACK) {//case 3
                w->right->color = BLACK;
                w->color = RED;
                rbt_left_rotate(t, w);
                w = x->parent->left;
            } else {
                w->color = x->parent->color; //case 4
                x->parent->color = BLACK;
                w->left->color = BLACK;
                rbt_right_rotate(t, x->parent);
                x = t->root;
            }
        }
    }//while

    x->color = BLACK;
}

RBTNode* rbt_minimum(RBTree* t, RBTNode* r) {
    while (r->left != t->nil) {
        r = r->left;
    }
    return r;
}

void clear_rbt_node_post(RBTree* t, RBTNode* r) {
    if (r != t->nil) {
        clear_rbt_node_post(t, r->left);
        clear_rbt_node_post(t, r->right);
        if (r != NULL)
            free(r);
    }
}

void display_rbt_node(RBTree* t, RBTNode* r) {
    if (r != t->nil) {
        display_rbt_node(t, r->left);
        /*
                printf("%d\n", r->key);
         */
        printf("%d ", r->key);
        display_rbt_node(t, r->right);
    }
}

void display_rbt_node_prev(RBTree* t, RBTNode* r) {
    if (r != t->nil) {
        /*
                printf("%d\n", r->key);
         */
        printf("%d ", r->key);
        display_rbt_node_prev(t, r->left);
        display_rbt_node_prev(t, r->right);
    }
}

void display_rbt_node_post(RBTree* t, RBTNode* r) {
    if (r != t->nil) {
        display_rbt_node_post(t, r->left);
        display_rbt_node_post(t, r->right);
        /*
                printf("%d\n", r->key);
         */
        printf("%d ", r->key);
    }
}

void show_rbt_node(RBTree* t, RBTNode* r, int high, int n) {
    if (r != t->nil) {
        show_rbt_node(t, r->right, high + 7, n + 1);
        int i = 0;
        while (i != high) {
            if (i % 7 == 0) {
                if (i >= 7 * n)
                    printf("|");
                else
                    printf(" ");
            } else
                printf(" ");
            i++;
        }
        if (r->color == RED)
            printf("|-<R>");
        else printf("|-<B>");
        printf("%2d-\n", r->key);

        show_rbt_node(t, r->left, high + 7, n + 1);
    } else {
        int i = 0;
        while (i != high) {
            if (i % 7 == 0) {
                if (i >= 7 * n)
                    printf("|");
                else
                    printf(" ");
            } else
                printf(" ");
            i++;
        }
        printf("|-NIL\n");
    }
}

测试程序main.c,用随机数进行插入、删除测试,多次测试没有问题

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/* 
 * File:   main.c
 * Author: weng
 *
 * Created on 2018年11月8日, 下午9:39
 */

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "rb_tree.h"

/*
 * 
 */
#define N_NODES 50
#define ARRAYSIZE 100001

int main(int argc, char** argv) {
    int i, n = 0;
    srand(time(0));
    int array[ARRAYSIZE];
    memset(array, -1, sizeof (array));

    RBTree* t = create_rbtree();
    for (i = 0; i < N_NODES; i++) {
        int num = rand() % N_NODES;
        insert_rbt_node(t, num);

        /*
                num = i;
                insert_rbt_node(t, num);
         */

        if (num != array[num]) {
            printf("插入: %d \n", num);
            array[num] = num;
            n++;
        } else {
            printf("重复插入 %d\n", num);
        }
    }
    printf("array: \n");
    for (int i = 0; i < ARRAYSIZE; i++)
        if (array[i] != -1)
            printf("%d ", array[i]);
    printf("\nhow many: %d\n", n);
    printf("display: \n");
    display_rbt(t);
    display_rbt_prevorder(t);
    display_rbt_postorder(t);

    show_rbt(t);

    for (i = 0; i < N_NODES; i++) {
        int num = rand() % N_NODES;
        remove_rbt_node(t, num);

        /*
                num = i;
                remove_rbt_node(t, num);
         */

        if (num == array[num]) {
            printf("删除: %d \n", num);
            array[num] = -1;
            n--;
        } else {
            printf("重复删除或不存在 %d\n", num);
        }
    }
   
    show_rbt(t);
    printf("array: \n");
    for (int i = 0; i < ARRAYSIZE; i++)
        if (array[i] != -1)
            printf("%d ", array[i]);
    printf("\nhow many: %d\n", n);
    printf("display: \n");
    display_rbt(t);
    display_rbt_prevorder(t);
    display_rbt_postorder(t);

    clear_rbtree(t);
    free(t);

    return (EXIT_SUCCESS);
}

这是随机插入20次并删除20次的整个过程

其他几次测试结果图

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值