实现红黑树的插入

观察红黑树的四种情况

在这里插入图片描述
根据红黑树的五条性质:

  1. 节点为红色或黑色
  2. 根是黑色
  3. 叶子节点(外部节点,空节点)为黑色
  4. 红节点的子节点为黑色,红节点的父节点为黑色,根节点到叶子节点的所有路径不能有两个连续的红色节点
  5. 任意节点到叶子节点所有路径包含相同数目的红色节点

可以看到,如果把某一层的红色节点和上一层父节点合并成一个节点,就变成了一个满足如下条件的四阶B树:

  1. 红黑树黑色节点数与4阶B树节点总数相等
  2. 所有B树节点,黑节点永远是父节点,红节点是子节点,黑节点在中间,红节点在两边

由这四种B树节点类型,插入节点情况分为三个大类:

  1. 插入节点后元素数超过3个,向上溢出(存在uncle节点且为红的情况,不涉及左右旋,只涉及颜色的调整和B树结点的分裂,同时将上溢的祖父节点当作新插入节点插入上一层判断)
  2. 插入节点父节点为黑(插入节点为红色节点,直接插入满足红黑树性质,不做调整)
  3. 插入节点父节点为红(uncle节点或不存在,或存在且为黑)

由此来实现我们的代码:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef enum{
    RED,
    BLACK
}Color;

typedef struct RBTreeNode{
    struct RBTreeNode* _left;
    struct RBTreeNode* _right;
    struct RBTreeNode* _parent;
    int data;
    Color _col;
}RBTreeNode;

RBTreeNode* createRBTreeNode(int data){
    RBTreeNode* node =(RBTreeNode*)malloc(sizeof(RBTreeNode));
    if(!node){
        fprintf(stderr, "Memory allocation failed\n");  
        exit(EXIT_FAILURE); 
    }
    node->_left = NULL;
    node->_right=NULL;
    node->_parent=NULL;
    node->data=data;
    node->_col=RED;
    return node;
}

RBTreeNode* search(RBTreeNode* T,int key){
    while(T!=NULL&&key!=T->data){
        if(key<T->data){
            T=T->_left;
        }
        else
            T=T->_right;
    }
    return T;
}

void RotateL(RBTreeNode* parent,RBTreeNode* T){/左旋操作,重点是将该节点右孩子的左孩子变为该节点的右孩子,该节点变为右孩子的左孩子
    RBTreeNode* subR=parent->_right;
    RBTreeNode* subRL=subR->_left;
    parent->_right=subRL;
    if(subRL){
        subRL->_parent=parent;
    }
    RBTreeNode* grand=parent->_parent;
    subR->_left=parent;
    parent->_parent=subR;

    if(grand==NULL){
        T=subR;
        T->_parent=NULL;
    }
    else{
        if(grand->_left==parent){
            grand->_left=subR;
        }
        else{
            grand->_right=subR;
        }
        subR->_parent=grand;
    }
}

void RotateR(RBTreeNode* parent,RBTreeNode* T){//右旋操作,与左旋操作轴对称
    RBTreeNode* subL=parent->_left;
    RBTreeNode* subLR=subL->_right;
    parent->_left=subLR;
    if(subLR){
        subLR->_parent=parent;
    }
    RBTreeNode* grand=parent->_parent;
    subL->_right=parent;
    parent->_parent=subL;

    if(grand==NULL){
        T=subL;
        T->_parent=NULL;
    }
    else{
        if(grand->_left==parent){
            grand->_left=subL;
        }
        else{
            grand->_right=subL;
        }
        subL->_parent=grand;
    }
}

bool insert(RBTreeNode** T,int data){//指向指针的指针
    RBTreeNode* cur = createRBTreeNode(data);  
    if (*T == NULL) {  
        *T = cur;  
        (*T)->_col = BLACK; // 第一个节点通常是黑色的  
        return true;  
    }  
    RBTreeNode* parent = NULL;  
    RBTreeNode* current = *T;  
    while(current){
        if(current->data<data){
            parent =current;
            current=current->_right;
        }
        else if(current->data>data){
            parent=current;
            current=current->_left;
        }
        else{
            return false;
        }
    }//遍历获取插入节点的parent

    if(parent->data>data){
        parent->_left=cur;
    }
    else{
        parent->_right=cur;
    }
    cur->_parent = parent;  //将插入节点的parent指向真正的parent

    while(parent &&parent->_col==RED){
        RBTreeNode* grand=parent->_parent;
        if(grand->_left==parent){
            RBTreeNode* uncle=grand->_right;
            //1:u存在且为红,变色,向上溢出
            if(uncle&&uncle->_col==RED){
                parent->_col=BLACK;
                uncle->_col=BLACK;
                grand->_col=RED;

                //向上溢出
                cur=grand;
                parent=cur->_parent;
            }
            else{
                //      g
                //    p   u
                //  c
                if(cur==parent->_left){
                    RotateR(grand,(*T));
                    parent->_col=BLACK;
                    grand->_col=RED;
                }
                else{
                //      g
                //    p   u
                //      c
                    RotateL(parent,(*T));
                    RotateR(grand,(*T));
                    cur->_col=BLACK;
                    grand->_col=RED;
                }

                break;
            }
        }
        else{// (grandfather->_right == parent)
            RBTreeNode* uncle=grand->_left;
            if(uncle&&uncle->_col==RED){
                parent->_col=BLACK;
                uncle->_col=BLACK;
                grand->_col=RED;

                //向上溢出
                cur=grand;
                parent=grand->_parent;
            }
            else{
                    //    g
					//  u   p
					//        c
                if(cur==parent->_right){
                    RotateL(grand,(*T));
                    grand->_col=RED;
                    parent->_col=BLACK;
                }
                else{
                    //    g
					//  u   p
					//    c
                    RotateR(parent,(*T));
                    RotateL(grand,(*T));
                    grand->_col=RED;
                    cur->_col=BLACK;
                }
                break;
            }
        }
    }
    printf("%d\n",cur->data);
    (*T)->_col=BLACK;
    return true;
}


void inorderTraversal(RBTreeNode* root) {  //中序遍历红黑树
    if (root != NULL) {  
        inorderTraversal(root->_left);  
        printf("%d(%s) ", root->data, root->_col == RED ? "RED" : "BLACK");  
        inorderTraversal(root->_right);  
    }  
}

int main() {  
    RBTreeNode* root = NULL;
    bool flag=true;
    int num[]={7,3,18,10,22,8,11,26};
    for(int i=0;i<8;i++){
        if(!flag){
            break;
        }
        flag=insert(&root,num[i]);
    }
      
  
    printf("Inorder Traversal of the created RBTree is \n");  
    inorderTraversal(root);  
    printf("\n");  
  
    return 0;  
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值