高级数据结构及算法:红黑树

本文详细介绍了红黑树的特点,包括其颜色规定、平衡性质,并讲解了插入和删除操作,如旋转、颜色翻转等,帮助读者深入理解这种高级数据结构。
摘要由CSDN通过智能技术生成

红黑树

1. 特点

《算法》中对红黑树的定义(针对的是线的颜色):

  1. 红色的线永远是左侧链接。(强行的规定)
  2. 没有一个节点同时链了两条红色的线。(也就是没有4-node)
  3. 任何从根到叶子节点的路径上有相同颜色的黑线。(黑线节点完美平衡)

红黑树合并为2-3查找树:
在这里插入图片描述
右侧有红色的线,要先通过旋转变为左侧的线,再合并:
在这里插入图片描述
合并的过程实质上是把红色的线拉成平的,就能清晰的看出2-3树和红黑树的关系

在这里插入图片描述
我们会把红线的红色信息放在子节点上,让子节点记录红色

红黑树中的红节点是什么意思? 根据上述内容用自己的话表达

2. 操作

2.1 旋转

按照下图书写左旋和右旋函数
(注意书写q,p,b的关系)
(还要注意红线是如何转移的)
在这里插入图片描述
对应上图写出左旋和右旋操作

#include <iostream>
using namespace std;

enum COLOR{
   RED,BLACK};        // 枚举红黑两种颜色

template <typename T>
class _Node{
   
public:
        T val;
        COLOR color = BLACK;               // 定义颜色
        _Node* left;
        _Node* right;
        _Node(const T& val):val(val),left(nullptr),right(nullptr){
   }
        _Node(const T& val,_Node* left,_Node* right):val(val),left(left),right(right){
   }
};

typedef _Node<int> Node;
// 右旋操作
Node* RotateRight(Node* root){
   
        Node* q = root;
        Node* p = root->left;
        Node* b = p->right;
        /* 转后 */
        p->right = q;
        q->left = b;
        /* 颜色变换 */
        p->color = q->color;
        q->color = RED;
        return p;
}
// 左旋操作
Node* RotateLeft(Node* root){
   
        Node* p = root;
        Node* q = p->right;
        Node* b = q->left;
        /* 转后 */
        q->left = p;
        p->right = b;
        /* 颜色变换 */
        q->color = p->color;
        p->color = RED;
        return q;
}

// 画一下树
void Preorder(Node* root){
   
        if(nullptr == root) return;

        if(root->left){
   
                cout << root->val << "--" << root->left->val;
                if(root->left->color == RED) cout << "[color=red]";
                cout << endl;
        }
        if(root->right){
   
                cout << root->val << "--" << root->right->val;
                if(root->right->color == RED) cout << "[color=red]";
                cout << endl;
        }

        Preorder(root->left);
        Preorder(root->right);
}

int main(){
   
        // 插入顺序为1,2,3
        Node a(1);
        Node b(2);
        Node c(3);
        c.color = RED;
        a.right = &b;
        b.right = &c;

        Preorder(&a);
        a.right = RotateLeft(&b);        // 以2为基准左旋
        Preorder(&a);

        a.right = RotateRight(&c);       // 再以3为基准右旋,又旋转回去了
        Preorder(&a);
}

结果为:

// 原树型
1--2
2--3[color=red]
// 以2为基准左旋
1--3
3--2[color=red]
// 再以3为基准右旋
1--2
2--3[color=red]

对应树的变换如图所示:
在这里插入图片描述

2.2 颜色翻转

颜色翻转:两个子节点由红色变为黑色,父节点由黑色变为红色,或者反过来
在这里插入图片描述

// 不为空且为红色
bool IsRed(Node* root){
   
        return nullptr!=root && root->color==RED;
}
// 做颜色翻转
Node* FlipColor(Node* root){
   
        if(IsRed(root->left) && IsRed(root->right)){
        // 左子节点和右子节点都是红色,进行颜色翻转
                root->left->color = BLACK;
                root->right->color = BLACK;
                root->color = RED;
        }
        return root;
}

2.3 插入

往一个2-node节点底部插入新的节点

按照BST遍历,新插入的节点标记为红色
在这里插入图片描述
如果新插入的节点在父节点的右子节点,则需要进行左旋操作
在这里插入图片描述

往一个3-node节点底部插入新的节点
  1. 插入的节点比现有的两个节点都大,新插入的节点连接到右边子树上,颜色反转
    在这里插入图片描述

  2. 插入的节点比现有的两个节点都小,新插入的节点连接到最左侧,以c为基准右旋颜色反转
    在这里插入图片描述

  3. 插入的节点的值位于两个节点之间,新节点插入到左侧节点的右子节点,先以a为基准左旋,再以c为基准右旋颜色反转
    在这里插入图片描述

找到规律并获得插入方法

由此可找到规律,对下面的操作按顺序依次执行,就可以完成红黑树的插入:

  1. 如果右子节点为红,左子节点不为红,要做一次左旋
  2. 如果左子节点为红,左子节点的左子节点也为红,要做一次右旋
  3. 如果左子节点为红,右子节点也为红,要做颜色翻转
// 形成正规的红黑树
Node* Blance(Node* root){
   
        if(IsRed(root->right) && !IsRed(root->left)) root = RotateLeft(root);
        if(IsRed(root->left) && IsRed(root->left->left)) root = RotateRight(root);
        
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值