算法导论:c++实现红黑树

数据结构

性质
这里写图片描述

这里写图片描述
这里定义一个结构体保存颜色

enum colorRB
{
    black = 0,
    red,
};
struct TreeNode_RB {
    int val;
    colorRB color;
    TreeNode_RB *left;
    TreeNode_RB *right;
    TreeNode_RB *parent;
    TreeNode_RB(int x, colorRB c) : val(x), left(NULL), right(NULL), parent(NULL),color(c) {}
};

旋转

这里写图片描述

左旋

这里写图片描述

/*红黑树左旋*/
void left_roate(TreeNode_RB *root,TreeNode_RB *x) //x称为y的左子树,y的左子树成为x的右子树
{
    TreeNode_RB *y = x->right;  //右子树左旋
    x->right = y->left;
    if (y->left != NULL) {
        y->left->parent = x;    //y左子树非空
    }
    y->parent = x->parent;  //置y的父节点
    if (x->parent == NULL) {
        root = y;
    }
    else if(x->parent->left==x)
    {
        x->parent->left = y;
    }
    else
    {
        x->parent->right = y;
    }
    y->left = x;    //y成为x左子树
    x->parent = y;  //y称为x的父节点
}
右旋
void right_roate(TreeNode_RB *root, TreeNode_RB *y) //y成为x的右子树,x的右子树成为y的左子树
{
    TreeNode_RB *x = y->left;   //左子树右旋
    y->left = x->right;
    if (x->right != NULL) {
        x->right->parent = y;   //x右子树非空
    }
    x->parent = y->parent;  //置x的父节点
    if (y->parent == NULL) {
        root = x;
    }
    else if (y->parent->left == y)
    {
        y->parent->left = x;
    }
    else
    {
        y->parent->right = x;
    }
    x->right = y;   //x成为y右子树
    y->parent = x;  //x成为y的父节点
}
测试
int main()
{
    TreeNode_RB *r1 = new TreeNode_RB(15,black);
    TreeNode_RB *r2 = new TreeNode_RB(6,red);
    TreeNode_RB *r3 = new TreeNode_RB(18,black);
    TreeNode_RB *r4 = new TreeNode_RB(3,black);
    TreeNode_RB *r5 = new TreeNode_RB(7,black);

    r1->left = r2;
    r1->right = r3;
    r2->parent = r1;
    r2->left = r4;
    r2->right = r5;
    r3->parent = r1;

    r4->parent = r2;
    r5->parent = r2;
    right_roate(r1, r2);

}

插入

插入就比较复杂了,涉及红黑树性质的调整,插入节点一致置颜色为红色,后再调整
这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

void RB_insert_fixup(TreeNode_RB *root, TreeNode_RB *z) {
    while (z->parent->color==red)
    {
        if (z->parent->parent->left==z->parent) //z的父节点是左子树
        {
            TreeNode_RB *y = z->parent->parent->right;  //叔叔节点
            if (y->color == red) //叔叔节点是红色,case 1
            {
                z->color = black;   //重新着色
                z->parent->color = black;
                z->parent->parent->color = red;
                z = z->parent->parent;  //指针上移
            }
            else if(z->parent->right==z)// 叔叔节点是黑色,且z是右子树,case 2
            {
                z = z->parent;
                left_roate(root, z);    //左旋
            }
            // 叔叔节点是黑色,且z是左子树,case 3
            z->parent->color = black;
            z->parent->parent->color = red;
            right_roate(root, z->parent->parent);
        }
        else
        {
            TreeNode_RB *y = z->parent->parent->left;   //叔叔节点
            if (y->color == red) //叔叔节点是红色,case 1
            {
                z->color = black;   //重新着色
                z->parent->color = black;
                z->parent->parent->color = red;
                z = z->parent->parent;  //指针上移
            }
            else if (z->parent->right == z)// 叔叔节点是黑色,且z是右子树,case 2
            {
                z = z->parent;
                right_roate(root, z);   //左旋
            }
            // 叔叔节点是黑色,且z是左子树,case 3
            z->parent->color = black;
            z->parent->parent->color = red;
            left_roate(root, z->parent->parent);
        }
    }
}

/*红黑树插入*/
void RB_insert(TreeNode_RB *root, TreeNode_RB *z) {
    TreeNode_RB *y = NULL;  //y标记node的父指针
    TreeNode_RB *x = root;  //x用于向下探测
    z->color = red; //将待插入节点颜色置为红色
    while (x != NULL)
    {
        y = x;
        if (root->val < x->val) {
            x = x->left;
        }
        else
        {
            x = x->right;
        }
    }
    z->parent = y;
    if (y == NULL) {
        root = z;
    }
    else if (z->val<y->val)
    {
        y->left = z;
    }
    else
    {
        y->right = z;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值