【数据结构】图解红黑树以及代码实现

news2024/9/21 0:40:21

目录

一、相关概念

性质

二、图解

1、插入操作

2、parent在左边情况1:cur为红色节点parent也是红色节点、uncle也为红色节点

3、parent在左边情况2:cur为红色节点parent也是红色节点、uncle为黑色或者是空,cur是parent的left

4、parent在左边情况3:cur为红色节点parent也是红色节点、uncle为黑色或者是空,cur是parent的right

5、parent在右边情况1:cur为红色节点parent也是红色节点、uncle也为红色节点

6、parent在右边情况2:cur为红色节点parent为红色节点、uncle为黑色或者是空,cur是parent的right

7、parent在右边情况3:cur为红色节点parent为红色节点、uncle为黑色或者是空,cur是parent的left

三、代码实现

1、准备节点

2、实现插入

3、 代码实现


一、相关概念

红黑树是一种自平衡的二叉查找树

红黑树是计算机科学中广泛使用的数据结构,通常用于实现关联数组等数据结构,以保证在最坏情况下仍具有较好的查找性能。下面是其特点和性质:

  1. 节点颜色:每个节点都有一个颜色属性,可以是红色或黑色。
  2. 根节点为黑:红黑树的根节点总是黑色的。
  3. 叶节点为黑:所有叶子节点(NIL)都是黑色的。这里的叶子节点指的是没有子节点的空链接。
  4. 路径长度限制:从根节点到任何叶子节点的简单路径上,均不会出现两个连续的红色节点,这意味着没有任何一个路径会比其它路径长出两倍。
  5. 查找效率:红黑树可以在 O(log N) 时间内完成查找、增加、删除等操作,其中 N 是树中元素的数量。

此外,红黑树的本质是对概念模型2-3-4树的一种实现。2-3-4树是阶数为4的B树,也是平衡多路查找树的一种,它通过保持树的平衡来确保即使在最坏情况下也能保持 O(Log N) 的时间复杂度进行查找操作。

性质
  1. 最长路径是最短路径的2倍
  2. 根节点是黑色的
  3. 如果一个节点是红色的,那么他的两个孩子节点是黑色的
  4. 对于每个节点,该节点到其所有后代的叶子节点的简单路径上均包含相同数目的黑色节点

二、图解

1、插入操作

每次插入节点的颜色都为红色,按照二叉搜索树的方式插入后,开始从插入的节点向上调整,使得这棵树满足红黑树上述的性质,在进行调整的过程中大致左右树类似分为3中情况,在调整之前的插入部分图解如下:

2、parent在左边情况1:cur为红色节点parent也是红色节点、uncle也为红色节点

3、parent在左边情况2:cur为红色节点parent也是红色节点、uncle为黑色或者是空,cur是parent的left

这种情况不可能是刚插入cur节点而引起的,因为此时grandparent是黑色的,此时parent路径上比uncle路径上的黑色节点少一个,所以这种情况是发生在调整的过程中的。

4、parent在左边情况3:cur为红色节点parent也是红色节点、uncle为黑色或者是空,cur是parent的right

这种情况也是发生在向上调整的过程中的

5、parent在右边情况1:cur为红色节点parent也是红色节点、uncle也为红色节点

与parent是grandparent的左边类型,右边的操作全部镜像

6、parent在右边情况2:cur为红色节点parent为红色节点、uncle为黑色或者是空,cur是parent的right

与上述parent是grandparent左边的情况2镜像相同,同样发生在调整的 过程中

7、parent在右边情况3:cur为红色节点parent为红色节点、uncle为黑色或者是空,cur是parent的left

与上述情况类型,将情况3转变为情况2去处理

三、代码实现

1、准备节点

首先一颗红黑树的节点需要哪些字段呢?需要数据域,以及左孩子指针右孩子指针还需存储他的父亲节点的指针,其次就是这个节点颜色

1.字段

2、实现插入

首先红黑树的插入主要分为两步将节点按照红色进行插入,插入方法与二叉搜索树插入相同。插入完成后按照其性质进行调整(左右旋转图示详解在AVL树)

插入

调整

插入节点颜色是红色,此时如果他的父亲节点也是红色,那么就不满足红黑树的性质,此时就需要去进行分情况调整,主要情况在二中详细图示

3、 代码实现
#include<iostream>
using namespace std;

/**
 * 红黑树的颜色
 */
enum COLOR {
RED,
BLACK
};

/**
 * 红黑树节点
 */
typedef struct RBTNode {
int val;
RBTNode* left;
RBTNode* right;
RBTNode* parent;
COLOR color;
}RBTNode, *TreeNode;

/**
 * 创建并初始化一个根节点
 * @param val
 * @return
 */
TreeNode NewRBTreeNode (int val) {
    auto node = (TreeNode) malloc(sizeof(RBTNode));
    node->val = val;
    node->color = RED;
    node->left = node->right = node->parent = nullptr;
    return node;
}

/**
 * 右旋
 * @param root 根节点
 * @param parent 旋转节点
 */
void rotateRight(TreeNode& root, TreeNode& parent) {
    TreeNode subL = parent->left;
    TreeNode subLR = subL->right;
    TreeNode pParent = parent->parent;

    parent->left = subLR;
    subL->right = parent;
    if (subLR != nullptr) subLR->parent = parent;
    parent->parent = subL;

    if (parent == root) {
        root = subL;
        subL->parent = nullptr;
    } else if (parent == pParent->left) {
        pParent->left = subL;
        subL->parent = pParent;
    } else {
        pParent->right = subL;
        subL->parent = pParent;
    }
}

/**
 * 左旋
 * @param root 根节点
 * @param parent 旋转节点
 */
void rotateLeft(TreeNode& root, TreeNode& parent) {
    TreeNode subR = parent->right;
    TreeNode subRL = subR->left;
    TreeNode pParent = parent->parent;

    parent->right = subRL;
    subR->left = parent;
    if (subRL != nullptr) subRL->parent = parent;
    parent->parent = subR;

    if (parent == root) {
        root = subR;
        subR->parent = nullptr;
    } else if (parent == pParent->left) {
        pParent->left = subR;
        subR->parent = pParent;
    } else {
        pParent->right = subR;
        subR->parent = pParent;
    }
}

/**
 * 插入
 * @param root 根节点
 * @param val  要插入的元素
 * @return
 */
bool Insert(TreeNode& root,int val) {
    if (root == nullptr) {
        root = NewRBTreeNode(val);
        root->color = BLACK;
        return true;
    }

    TreeNode cur = root, parent = nullptr;
    while (cur) {
        if (cur->val > val) {
            parent = cur;
            cur = cur->left;
        } else if (cur->val < val) {
            parent = cur;
            cur = cur->right;
        } else {
            return false;
        }
    }

    TreeNode node = NewRBTreeNode(val);
    if (parent->val > val) parent->left = node;
    else parent->right = node;
    node->parent = parent;

    cur = node;
    // 调整的前提是插入节点是红色的且他的父亲也是红色 或者 在调整过程中使得cur是红色的parent也是红色的
    while (parent != nullptr && parent->color == RED) {
        TreeNode grandParent = parent->parent;  // 只要parent不为空且为红色,这个节点就不可能为空,因为根节点颜色是黑色的
        if (parent == grandParent->left) {
            TreeNode uncle = grandParent->right;
            if (uncle != nullptr && uncle->color == RED) {
                // case1:  red(cur parent uncle)
                grandParent->color = RED;
                uncle->color = parent->color = BLACK;

                cur = grandParent;
                parent = cur->parent;
            } else {
                if (cur == parent->right) {
                    // case3: red(cur parent) black or null(uncle)  cur == parent->right
                    rotateLeft(root, parent);
                    TreeNode tmp = parent;
                    parent = cur;
                    cur = tmp;
                }  // case3 -> case2

                // case2: red(cur parent) black or null(uncle) cur == parent.left
                rotateRight(root, grandParent);
                grandParent->color = RED;
                parent->color = BLACK;
            }
        } else {
            TreeNode uncle = grandParent->left;
            if (uncle != nullptr && uncle->color == RED) {
                // case1: red(cur parent uncle)
                parent->color = uncle->color = BLACK;
                grandParent->color = RED;

                cur = grandParent;
                parent = cur->parent;
            } else {
                if (cur == parent->left) {
                    // case3: red(cur parent) black or null(uncle)  cur == parent->left
                    rotateRight(root, parent);
                    TreeNode tmp = cur;
                    cur = parent;
                    parent = tmp;
                }

                // case2: red(cur parent) black or null(uncle) cur == parent.right
                rotateLeft(root, grandParent);
                grandParent->color = RED;
                parent->color = BLACK;
            }
        }
    }
    root->color = BLACK;
    return true;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1702676.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

边缘计算网关的市场价格趋势-天拓四方

在数字化转型的大潮中&#xff0c;边缘计算网关作为连接云端与终端设备的核心节点&#xff0c;其重要性日益凸显。然而&#xff0c;面对市场上琳琅满目的边缘计算网关产品&#xff0c;对于许多企业和个人用户来说&#xff0c;边缘计算网关的价格成为选择产品时的重要考量因素。…

wordpress主题 ACG美化插件v3.4.2支持zibll主题7b2主题美化

独具一格的二次元风格&#xff0c;打造全新的子比美化方向 大部分代码均为CSS、JS做成插件只是为了方便懒人小白站长 后台全功能一览&#xff0c;大部分美化均为网上通用流传&#xff0c;

数据集006:中药材识别数据集(含数据集下载链接)

数据集简介&#xff1a; 中药材共5类 900张图片 分别是百合 枸杞 党参 槐花 金银花 部分代码&#xff1a; def get_data_list(target_path,train_list_path,eval_list_path):生成数据列表#存放所有类别的信息class_detail []#获取所有类别保存的文件夹名称data_list_pat…

磁盘管理以及文件系统08

1、为什么要对磁盘进行分区&#xff1f; 业务层面&#xff1a;为满足一定的需求所是做的特定操作。 2、硬盘是什么&#xff0c;以及硬盘的作用 硬盘&#xff1a;计算机的存储设备&#xff0c;一个或者多个带磁性的盘组成的&#xff0c;可以在盘片上进行数据的读写。硬盘的最…

全方位质量保障!龙蜥在内核、软件包、容器镜像、三方模块的 CI 工程实践

编者按&#xff1a;在海量的代码测试和构建中&#xff0c; CI(Continuous Integration)在代码提交阶段&#xff0c;对提高软件质量和开发效率起到了至关重要的作用。2023 龙蜥操作系统大会全面繁荣开发者生态分论坛上&#xff0c;龙蜥社区 QA SIG Maintainer、联通数科 CUlinux…

【UE5.4】猫猫都能看懂的Android打包新版攻略

开发未动&#xff0c;兼容先行&#xff01; 亲妈级攻略&#xff0c;一步一截图&#xff01; 铲除一切奇怪的报错&#xff01; 引言 最近在入坑Unreal Engine&#xff0c;在尝试进行Android打包时遇到了巨大的困难&#xff1b;不管怎么打包都是奇怪的Unknown Error报错&#…

MacBook Air M3游戏无法安装怎么办 MacBook Air可以玩3A游戏吗

在数字化迅速发展的今天&#xff0c;MacBook Air M3凭借其轻薄便携和强大的处理能力&#xff0c;成为了许多消费者的首选MacBook Air M3能够满足日常的工作和学习需求&#xff0c;然而&#xff0c;用户尝试在MacBook Air M3上安装和运行游戏时&#xff0c;经常遇到一些困难&…

如何免费把微信视频号的视频下载下来?电脑手机都可使用

今天&#xff0c;我将为大家分享一个实用的技巧&#xff1a;如何免费将微信视频号的视频下载下来。 微信视频号作为一个流行的短视频平台&#xff0c;拥有大量优质内容。然而&#xff0c;由于平台政策限制&#xff0c;我们无法直接下载视频。不过&#xff0c;别担心&#xff0…

nvm安装教程及使用nvm管理多个node版本

文章目录 前言一、nvm 安装教程温馨提示macOS/LinuxWindows 二、安装 node 前言 工作中&#xff0c;你可能会遇到以下场景&#xff1a; 我想使用 pnpm 命令安装依赖&#xff0c;但是在使用 pnpm 命令时提示如下 $ pnpm -v ERROR: This version of pnpm requires at least No…

满帮集团 Eureka 和 ZooKeeper 的上云实践

作者&#xff1a;胡安祥 满帮集团&#xff0c;作为“互联网物流”的平台型企业&#xff0c;一端承接托运人运货需求&#xff0c;另一端对接货车司机&#xff0c;提升货运物流效率。2021 年美股上市&#xff0c;成为数字货运平台上市第一股。根据公司年报&#xff0c;2021 年&a…

521源码-免费游戏源码下载-闯梦江湖Q萌复古全网通手游服务端H5全攻略

闯梦江湖H5&#xff1a;Q萌复古全网通手游服务端全攻略 一、概述 闯梦江湖H5 是一款结合Q萌画风与复古情怀的全网通H5手游。我们为您提供了最新打包的Windows服务端&#xff0c;并附带了通用视频架设教程和GM网页授权后台工具&#xff0c;让您轻松搭建并管理自己的游戏世界。 …

现代前端工程化实践:Git、Husky、Commitlint与PNPM的协同作战

引言 Git Husky 与 Commitlint 是两个在 Git 工作流程中非常实用的工具&#xff0c;它们可以帮助团队维护代码质量和提交规范。Husky 是一个 Git 钩子管理器&#xff0c;允许你在仓库级别方便地配置钩子脚本&#xff1b;而 Commitlint 则是用来规范 Git 提交信息的工具&#x…

办公必备!一键拆分文件,效率翻倍的秘密

需求介绍 1、我有一张数据表“测试数据.xlsx” 2、我要根据A1“COUNTY_CODE”分类拆分成几张数据表&#xff08;这里从9657到9658共12类&#xff0c;就是拆分成12张数据表&#xff09; 3、根据12个分类&#xff0c;发送数据邮件给对应的收件人 4、收件人及抄送人、共同抄送人…

推导2维镜像变换(Reflection Transform)的公式

我们知道2维的旋转变换公式为 Q ( cos ⁡ ( θ ) sin ⁡ ( θ ) − sin ⁡ ( θ ) cos ⁡ ( θ ) ) Q\left( \begin{matrix} \cos \left( \theta \right)& \sin \left( \theta \right)\\ -\sin \left( \theta \right)& \cos \left( \theta \right)\\ \end{matrix} \r…

【java-数据结构18-队列】

上篇文章&#xff0c;我们已经完成了栈的学习&#xff0c;下面&#xff0c;我们将进行队列的学习&#xff0c;话不多说&#xff0c;上正文~ 1.队列 概念 队列&#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff0c;队列具有…

解决:java.util.concurrent.RejectedExecutionException

一 发现RejectedExecutionException错误 今天查看服务器的时候发现了一些java.util.concurrent.RejectedExecutionException错误&#xff0c;这个是由于线程池里的线程忙不过来报出的。如下图&#xff1a; 像这种 RejectedExecutionException 错误&#xff0c;表明在Java应…

捷报!恒瑞医药ADC创新药SHR-A1921卵巢癌适应症拟纳入突破性治疗品种公示

近日&#xff0c;恒瑞医药自主研发的TROP-2抗体偶联药物&#xff08;antibody-drug-conjugate, ADC&#xff09;注射用SHR-A1921用于治疗铂耐药复发上皮性卵巢癌、输卵管癌或原发性腹膜癌适应症被国家药品监督管理局药品审评中心拟纳入突破性治疗品种公示名单。今年3月&#xf…

ssm缴税管理系统-计算机毕业设计源码70555

摘 要 随着互联网大趋势的到来&#xff0c;社会的方方面面&#xff0c;各行各业都在考虑利用互联网作为媒介将自己的信息更及时有效地推广出去&#xff0c;而其中最好的方式就是建立网络管理系统&#xff0c;并对其进行信息管理。由于现在网络的发达&#xff0c;缴税管理系统的…

【RAG论文】检索信息中的噪音是如何影响大模型生成的?

前些天看到的两篇论文&#xff0c;论文标题为&#xff1a; 《The Power of Noise Redefining Retrieval for RAG Systems》《How Easily do Irrelevant Inputs Skew the Responses of Large Language Models》 主要讲述了检索文档是如何影响大模型输出的以及相关实验结果&…

基于ssm+vue图书管理系统

基于ssmvue图书管理系统 ssm477图书管理系统 相关技术 javassmmysqlvueelementui