红黑树

黑红树

使用的平台:vs2015

语言:c++

代码有部分是借鉴的

我是一只菜鸟,在平衡二叉树要旋转的时候总是绕道自己昏头转向,自己都弄不懂那棵树是怎么旋转的,其实我也是不太明白了,但是希望我的代码能够帮助你们解决问题。代码有错误,提前说啦!!

//核心函数:
//void rb_right_rotate(rbnode* g)
//void rb_left_rotate(rbnode* g)
//void rbt_insert_check(rbnode* node)
//int rbt_insert(rbtree* &tree, keyType key)
//void rbt_delete_check
//int is_black
//int rbt_delete
//左旋和右旋的代码基本相同,只需要更改right和left
//插入只有4中情况,而删除有六种
//检查部分需要细心看

    #include <iostream>

    using namespace std;

    #define COLOR_RED 0  
    #define COLOR_BLACK 1  

    typedef int keyType;

    // 定义而二叉树节点数据结构  
    struct BinaryTreeNode {
        keyType key;
        int color;
        BinaryTreeNode* parent; // 保存父节点  
        BinaryTreeNode* left; // left child  
        BinaryTreeNode* right; // right child  
        BinaryTreeNode*  next;

    };




    // 定义红黑树的结点
    typedef BinaryTreeNode rbnode;

    //  定义红黑树
    typedef BinaryTreeNode rbtree;



    //左旋和右旋的代码基本相同,只需要更改right和left
    //插入只有4中情况,而删除有六种

    void preorder(rbtree *g);

    void inorder(rbtree *g);

    void postorder(rbtree *g);
    void print(rbtree *g);

    //R
    void rb_right_rotate(rbnode* g) {
        rbnode * p = g->left;   //右转,p指向g的left

        //交换
        keyType k = g->key;

        g->key = p->key;
        p->key = k;
        //g的左节点是g的做节点的左节点
        g->left = p->left;
        if (NULL != p->left) {//右旋,p的left不能为空

            p->left->parent = g;
        }
        p->left = p->right;
        p->right = g->right;


        //这个if-else用于将g的父亲节点的left或right点指向p,如果g的父节点为不存在,则树的parent指向p
        if (NULL != g->right) {
            g->right->parent = p;
        }
        g->right = p;
    }

    // L 
    void rb_left_rotate(rbnode* g) {

        rbnode* p = g->right;
        keyType k = g->key;
        g->key = p->key;
        p->key = k;
        g->right = p->right;
        if (NULL != p->right) {
            p->right->parent = g;
        }
        p->right = p->left;
        p->left = g->left;
        if (NULL != g->left) {
            g->left->parent = p;
        }
        g->left = p;
    }

    // 插入后调整
    void rbt_insert_check(rbnode* node) {
        // CASE 1 :  如果节点等于根节点,则设置节点的颜色为黑色并返回。
        if (NULL == node->parent) {
            node->color = COLOR_BLACK;
            return;
        }
        // CASE 2 : 当节点的父节点为黑色时,所有功能都已满足,停止检查并返回  
        if (node->parent->color == COLOR_BLACK) {
            return;
        }

        // 父节点为红色,这意味着祖父节点存在。 
        rbnode* gf = node->parent->parent;
        rbnode* uf = (gf->left == node->parent) ? gf->right : gf->left;

        // CASE 3 : 当叔叔节点存在并且它是红时
        if (NULL != uf && uf->color == COLOR_RED) {
            // 设置父亲和叔叔黑色,设置祖父红色
            node->parent->color = COLOR_BLACK;
            uf->color = COLOR_BLACK;
            gf->color = COLOR_RED;
            // 然后重新检查来自CASE 1的祖父节点处的树。
            rbt_insert_check(gf);
            return;
        }

        // CASE 4 : 当叔叔是NULL或它的颜色是黑色。
        if (node->parent == gf->left) { // 该节点在其祖父的左边 
                                        // (a) LL model  
            if (node == node->parent->left) { //该节点在其父节点的左侧
                rb_right_rotate(gf);
            }
            // (b) LR model  
            else if (node == node->parent->right) { //该节点在其父节点的右侧
                rb_left_rotate(node->parent);
                rb_right_rotate(gf);
            }
        }
        else if (node->parent == gf->right) { //该节点在其祖父节点的右侧  
                                              // (c) RR model  
            if (node == node->parent->right) { //该节点在其父节点的右侧  
                rb_left_rotate(gf);
            }
            // (d) RL model  
            else if (node == node->parent->left) { //该节点在其父节点的左侧 
                rb_right_rotate(node->parent);
                rb_left_rotate(gf);
            }
        }
    }

    // 插入新的关键字  
    int rbt_insert(rbtree* &tree, keyType key) {
        if (NULL == tree) { // 树是否为空  
            tree = (rbtree*)malloc((sizeof(rbnode)));  //开辟空间
            tree->key = key;
            tree->color = COLOR_BLACK;//根为黑色
            tree->parent = tree->left = tree->right = NULL;
            return 1;
        }
        //寻找插入点 
        rbnode *n = tree, *p = tree->parent;
        while (NULL != n) {
            if (key == n->key) {  //插入值相同时,不用再插入
                return 0;
            }
            p = n;
            n = (key > p->key) ? p->right : p->left; //排序,有利于插入删除
        }
        // 插入节点
        n = (rbtree*)malloc((sizeof(rbnode)));
        n->key = key;
        n->color = COLOR_RED; //除了根节点外,插入的节点都是红色,当调整完后,方可恢复黑色
        n->parent = p;
        n->right = n->left = NULL;
        ((key > p->key) ? p->right : p->left) = n; //判断插入左节点还是右节点


        // 调整数 
        rbt_insert_check(n);

        return 1;
    }

    int is_black(rbnode * node) {
        if (node == NULL) return 1;
        if (node->color == COLOR_BLACK) return 1;
        return 0;
    }

    //检查删除调整后
    void rbt_delete_check(rbnode* p, bool delLeft) {
        rbnode * n = delLeft ? p->left : p->right;
        // case 1: n 是红
        if (NULL != n && n->color == COLOR_RED) {
            n->color = COLOR_BLACK;
            return;
        }
        // 其他子树至少一个节点
        rbnode * s = delLeft ? p->right : p->left;
        rbnode * sl = s->left;
        rbnode * sr = s->right;

        // case 2 : S 红 , p 左转
        if (s->color == COLOR_RED) {
            if (delLeft) {
                rb_left_rotate(p);
            }
            else {
                rb_right_rotate(p);
            }
            p = s;
            s = delLeft ? sl : sr;
            sl = s->left;
            sr = s->right;
        }
        // Other cases : S 黑  
        // SL 和 SR 黑  
        if (is_black(sl) && is_black(sr)) {
            // case 3 : P红,  S SL和 SR 黑 
            if (!is_black(p)) {
                p->color = COLOR_BLACK;
                s->color = COLOR_RED;
            }
            // case 4: P ,S, SL,SR 黑
            else {
                s->color = COLOR_RED;
                if (NULL == p->parent) {
                    return;
                }
                delLeft = (p == p->parent->left);
                rbt_delete_check(p->parent, delLeft);
            }
            return;
        }
        // SL 和 SR 有红色节点  
        if (delLeft) {
            if (is_black(sr)) {    // case 5(a) : delLeft 真 ,SR 黑 
                rb_right_rotate(s);
                sr = s->right;
            }
            rb_left_rotate(p);    // case 6(a) : p节点旋转
            sr->color = COLOR_BLACK;
        }
        else {
            if (is_black(sl)) {    // case 5(b) : delLeft 假 和SL 黑  
                rb_left_rotate(s);
                sl = s->left;
            }
            rb_right_rotate(p);    // case 6(b) :  p节点旋转 
            sl->color = COLOR_BLACK;
        }
    }

    // 删除一个节点 
    int rbt_delete(rbtree* &tree, keyType key) {
        if (NULL == tree) {
            return 0;
        }
        // 寻找节点 
        rbnode *curr, *temp;
        for (curr = tree;;) {
            if (key == curr->key) {
                break;
            }
            curr = (key > curr->key) ? curr->right : curr->left;
            if (NULL == curr) {
                return 0;
            }
        }
        //删除的有两个孩子
        if (NULL != curr->left && NULL != curr->right) {
            for (temp = curr->left; NULL != temp->right; temp = temp->right) {
            }
            curr->key = temp->key;
            curr = temp;
        }
        if (NULL == curr->parent) { // 判断是否树的根
            tree = (NULL == curr->left) ? curr->right : curr->left;
            if (tree != NULL) {
                tree->color = COLOR_BLACK;
                tree->parent = NULL;
            }
            free(curr);
            return 1;
        }
        // 删除节点  
        rbnode* fa = curr->parent;
        temp = (NULL == curr->left) ? curr->right : curr->left;
        bool delLeft = (fa->left == curr);
        if (NULL != temp) {
            temp->parent = fa;
        }
        delLeft ? fa->left = temp : fa->right = temp;
        if (curr->color != COLOR_RED) { // adjust after deletion  
            rbt_delete_check(fa, delLeft);
        }
        free(curr);
        return 1;
    }

    void preorder(rbnode *g)
    {
        if (g != NULL)
        {
            cout << g->key<< "  " ;

            preorder(g->left);

            preorder(g->right);



        }


    }

    void inorder(rbnode *g)
    {
        if (g != NULL)
        {
            inorder(g->left);

            cout << g->key<<"  ";

            inorder(g->right);
        }


    }

    void postorder(rbnode *g)
    {
        if (g != NULL)
        {
            postorder(g->left);



            postorder(g->right);

            cout << g->key << "  ";
        }


    }

    void print(rbnode *g)
    {
        //
        cout << "先序输出 :";

        preorder(g);


        cout << endl;
        cout << "中序输出 :" ;

        inorder(g);

        cout << endl;
        cout << "后序输出 :";
        postorder(g);

        cout << endl;

    }

    int main()
    {
        rbnode *p=NULL ;

        cout << "插入数据:\n" << endl;
        for (int i = 0; i <6; i++)
        {
            cout << i + 1 << endl;

            int a;
            cin >> a;
            rbt_insert(p,a);

            print(p);

            cout << endl;

        }


        //cout << "调整后:\n" << endl;
        //print(p);
        //

        cout << "删除数据 :\n" << endl;
        for (int i = 0; i <5; i++)
        {
            cout << i + 1 << endl;

            int a;
            cin >> a;
            rbt_delete(p, a);

            print(p);

            cout << endl;

        }

        system("pause");
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值