C语言 红黑树

29 篇文章 0 订阅
5 篇文章 0 订阅

红黑树简介

红黑树是每个节点都带有颜色属性的二叉查找树,颜色或红色或黑色。

红黑树的模拟过程可以看链接:InsertSortion

红黑树有五个性质:

性质1. 节点是红色或黑色。
性质2. 根节点是黑色
性质3. 每个叶节点(NIL节点,空节点)是黑色的。
性质4. 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
性质5. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。

实现过程

什么情况下会破坏红黑树呢?参照链接:红黑树(一)之 原理和算法详细介绍
除了根节点,插入的节点都是红色的。
总结一下就是出现以下几种情况:
这里写图片描述

对于前四种情况,我们通过左旋右旋操作去解决。(注:关于什么是左旋和右旋可以参照链接C语言 AVL树

最后一种情况,操作则不一样:
这里写图片描述
所以对于红黑树的插入从操作上来看则只是比AVL树多了最后一种情况。

代码实现

节点

typedef struct Bi{
    int val;
    int pos;

    int color;
    struct Bi *parent;
    struct Bi *left_child;
    struct Bi *right_child;
} Btree, *BtreePtr;

ADT:

#define COLOR(p)     ( (p==NULL) ? BLACK : (((BtreePtr)(p))->color) )
#define REB 1
#define BLACK 2

BtreePtr rightRotateRB(BtreePtr a) ;
BtreePtr leftRotateRB(BtreePtr a);
BtreePtr rightLeftRotateRB(BtreePtr a);
BtreePtr leftRightRotateRB(BtreePtr a);

BtreePtr _checkColor(BtreePtr p); //检查节点之后两层节点是否出现失衡,并让树平衡
BtreePtr _insertRBTree(BtreePtr p, const int key, const int pos);

BtreePtr insertRBTree(BtreePtr root, const int key, const int pos);

完整代码

#include <stdio.h>
#include <malloc.h>
#include <memory.h>
#define COLOR(p)     ( (p==NULL) ? BLACK : (((BtreePtr)(p))->color) )
#define REB 1
#define BLACK 2

typedef struct Bi{
    int val;
    int pos;
    int color;

    struct Bi *parent;
    struct Bi *left_child;
    struct Bi *right_child;
} Btree, *BtreePtr;

int midSearch(const BtreePtr a, const int key) {
    if (a != NULL) {
        if (key > a->val) {
            return midSearch(a->right_child, key);
        }
        else if(key < a->val) {
            return midSearch(a->left_child, key);
        }
        else {
            return a->pos;
        }
    }
    else {
        return -1;
    }
}

void freeTree(BtreePtr b) {
    if (b->right_child !=NULL) {
        freeTree(b->right_child);
    }
    if (b->left_child != NULL) {
        freeTree(b->left_child);
    }
}

BtreePtr leftRotateRB(BtreePtr p) {
    BtreePtr b = (BtreePtr)malloc(sizeof(Btree));
    b = p->right_child;
    p->right_child = b->left_child;
    p->color = REB;

    b->color = BLACK;
    b->left_child = p;
    b->parent = p->parent;
    b->left_child->parent = b;
    return b;
}

BtreePtr rightRotateRB(BtreePtr p) {
    BtreePtr b = (BtreePtr)malloc(sizeof(Btree));
    b = p->left_child;
    p->left_child = b->right_child;
    p->color = REB;

    b->color = BLACK;
    b->right_child = p;
    b->parent = p->parent;
    b->right_child->parent = b;
    return b;
}

BtreePtr rightleftRotateRB(BtreePtr p) {
    p->right_child = rightRotateRB(p->right_child);
    p = leftRotateRB(p);
    return p;
}

BtreePtr leftrightRotateRB(BtreePtr p) {
    p->right_child = leftRotateRB(p->right_child);
    p = rightRotateRB(p);
    return p;
}

BtreePtr _checkColor(BtreePtr p) {
    int p_color = COLOR(p);

    int right = COLOR(p->right_child);
    int left = COLOR(p->left_child);

    if (right == REB && left == BLACK) {
        int right_left = COLOR(p->right_child->left_child);
        int right_right = COLOR(p->right_child->right_child);

        if (right_right == REB) {
            p = leftRotateRB(p);
        }
        else if (right_left == REB) {
            p = rightleftRotateRB(p);
        }
    }

    else if (left == REB  && right == BLACK) {
        int left_right = COLOR(p->left_child->right_child);
        int left_left = COLOR(p->left_child->left_child);

        if (left_left == REB) {
            p = rightRotateRB(p);
        }
        else if (left_right == REB) {
            p = leftrightRotateRB(p);
        }
    }

    else if (right == REB && left == REB) {
        int left_right = COLOR(p->left_child->right_child);
        int left_left = COLOR(p->left_child->left_child);
        int right_left = COLOR(p->right_child->left_child);
        int right_right = COLOR(p->right_child->right_child);

        if (left_right == REB || left_left == REB || right_left == REB || right_right == REB) {
            if (p->parent != NULL) {
                p->color = REB;
            }
            p->left_child->color = BLACK;
            p->right_child->color = BLACK;
        }
    }
    return p;
}

BtreePtr _insertRBTree(BtreePtr p, const int key, const int pos) {
    if (p == NULL) {
        BtreePtr b = (BtreePtr)malloc(sizeof(Btree));
        if (b != NULL) {
            memset(b, 0, sizeof(Btree));
            b->val = key;
            b->pos = pos;
            b->color = REB;
            p = b;
        }
        else {
            return NULL;
        }
    }
    else
    {
        if (key < p->val) {
            p->left_child = _insertRBTree(p->left_child, key, pos);
            p->left_child->parent = p;
        }
        else {
            p->right_child = _insertRBTree(p->right_child, key, pos);
            p->right_child->parent = p;
        }
    }
    p = _checkColor(p);
    return p;
}

BtreePtr insertRBTree(BtreePtr root, const int key, const int pos) {
    if (root == NULL) {
        BtreePtr p = (BtreePtr)malloc(sizeof(Btree));
        if (p != NULL) {
            memset(p, 0, sizeof(Btree));
            p->val = key;
            p->pos = pos;
            p->color = BLACK;
            root = p;
        }
        else {
            puts("内存不足");
        }
    }
    else
    {
        root = _insertRBTree(root, key, pos);
    }
    return root;
}


int RBTreeSearch(const int *a, const int length, const int key) {
    BtreePtr root = NULL;
    for (int i = 0; i < length; i++) {
        root = insertRBTree(root, a[i], i);  //构建二叉树
    }
    int pos = midSearch(root, key);
    freeTree(root); //不能直接使用free(b)
    return pos;
}



void main() {
    const int length = 6;
    int my_array[6] = { 5, 7, 9,11 ,8,10};
    printf("%d \n", RBTreeSearch(my_array, length, 7));
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值