红黑树-自平衡二叉搜索树

news2024/12/24 10:06:11

一、简介

红黑树(Red-Black Tree)是一种自平衡的二叉搜索树,它的节点可以是红色或黑色。这个颜色的设计是为了满足红黑树的五个关键性质,确保树保持平衡和高效地支持插入、删除和搜索操作。

以下是红黑树的五个关键性质:

  1. 每个节点要么是红色,要么是黑色。
  2. 根节点是黑色的。
  3. 每个叶子节点(NIL节点,通常表示为黑色)是黑色的。
  4. 如果一个节点是红色的,那么它的两个子节点都是黑色的。
  5. 对于每个节点,从该节点到其后代任意叶子节点,经过的黑色节点的数量都相同。

这些性质确保了红黑树的平衡性,使得树的高度保持在可控范围内,从而保证了基本的搜索、插入和删除操作的时间复杂度为 O(log n),其中 n 是树中节点的数量。

红色节点和黑色节点的交替排列和上述性质的约束是为了保持树的平衡性。通过确保在树中的任何路径上都有相同数量的黑色节点,红黑树可以防止出现极端不平衡的情况,从而保证了树的高度保持在可控的范围内。红色节点的存在有助于确保在插入和删除节点时树能够重新平衡。

总之,红黑树中的红色节点和黑色节点是为了满足平衡性和其他性质而设计的,它们共同确保了红黑树的高效性和可预测性。

二、红黑树的操作

首先我们来看一个红黑树(红节点H,M也有叶子节点NIL没有画出了):

由此可见,红黑树并不是一个完美平衡二叉查找树,根结点P的左子树显然比右子树高,但左子树和右子树的黑结点的层数是相等的,也即任意一个结点到到每个叶子结点的路径都包含数量相同的黑结点(性质5)。所以我们叫红黑树这种平衡为黑色完美平衡
由于红节点总是插入在黑节点中,所以左子树与右子树最大的差距也不会超过2倍,这就保证了树的平衡性。
例如 :------,长度分别为5跟3,即5/3约等于1.6倍,显然没有超过2倍。

前面讲到红黑树能自平衡,它靠的是什么操作?三种操作:左旋、右旋和变色。

  • 左旋:以某个结点作为支点(旋转结点),其右子结点变为旋转结点的父结点,右子结点的左子结点变为旋转结点的右子结点,左子结点保持不变。如图3。
  • 右旋:以某个结点作为支点(旋转结点),其左子结点变为旋转结点的父结点,左子结点的右子结点变为旋转结点的左子结点,右子结点保持不变。如图4。
  • 变色:结点的颜色由红变黑或由黑变红。

三、实现

using System;

public enum NodeColor
{
    Red,
    Black
}

public class Node
{
    public int Data { get; set; }
    public Node Parent { get; set; }
    public Node Left { get; set; }
    public Node Right { get; set; }
    public NodeColor Color { get; set; }
}

public class RedBlackTree
{
    private Node root;

    // 插入节点
    public void Insert(int data)
    {
        var node = new Node { Data = data, Color = NodeColor.Red };
        if (root == null)
        {
            root = node;
            root.Color = NodeColor.Black;
        }
        else
        {
            InsertNode(root, node);
            FixTree(node);
        }
    }

    // 辅助方法:插入节点
    private void InsertNode(Node root, Node newNode)
    {
        if (newNode.Data < root.Data)
        {
            if (root.Left == null)
            {
                root.Left = newNode;
                newNode.Parent = root;
            }
            else
                InsertNode(root.Left, newNode);
        }
        else
        {
            if (root.Right == null)
            {
                root.Right = newNode;
                newNode.Parent = root;
            }
            else
                InsertNode(root.Right, newNode);
        }
    }

    // 辅助方法:修复红黑树性质
    private void FixTree(Node node)
    {
        while (node != root && node.Parent.Color == NodeColor.Red)
        {
            if (node.Parent == node.Parent.Parent.Left)
            {
                var uncle = node.Parent.Parent.Right;
                if (uncle != null && uncle.Color == NodeColor.Red)
                {
                    node.Parent.Color = NodeColor.Black;
                    uncle.Color = NodeColor.Black;
                    node.Parent.Parent.Color = NodeColor.Red;
                    node = node.Parent.Parent;
                }
                else
                {
                    if (node == node.Parent.Right)
                    {
                        node = node.Parent;
                        RotateLeft(node);
                    }
                    node.Parent.Color = NodeColor.Black;
                    node.Parent.Parent.Color = NodeColor.Red;
                    RotateRight(node.Parent.Parent);
                }
            }
            else
            {
                var uncle = node.Parent.Parent.Left;
                if (uncle != null && uncle.Color == NodeColor.Red)
                {
                    node.Parent.Color = NodeColor.Black;
                    uncle.Color = NodeColor.Black;
                    node.Parent.Parent.Color = NodeColor.Red;
                    node = node.Parent.Parent;
                }
                else
                {
                    if (node == node.Parent.Left)
                    {
                        node = node.Parent;
                        RotateRight(node);
                    }
                    node.Parent.Color = NodeColor.Black;
                    node.Parent.Parent.Color = NodeColor.Red;
                    RotateLeft(node.Parent.Parent);
                }
            }
        }
        root.Color = NodeColor.Black;
    }

    // 左旋
    private void RotateLeft(Node node)
    {
        var temp = node.Right;
        node.Right = temp.Left;
        if (temp.Left != null)
            temp.Left.Parent = node;
        if (temp != null)
            temp.Parent = node.Parent;
        if (node.Parent == null)
            root = temp;
        else if (node == node.Parent.Left)
            node.Parent.Left = temp;
        else
            node.Parent.Right = temp;
        temp.Left = node;
        if (node != null)
            node.Parent = temp;
    }

    // 右旋
    private void RotateRight(Node node)
    {
        var temp = node.Left;
        node.Left = temp.Right;
        if (temp.Right != null)
            temp.Right.Parent = node;
        if (temp != null)
            temp.Parent = node.Parent;
        if (node.Parent == null)
            root = temp;
        else if (node == node.Parent.Right)
            node.Parent.Right = temp;
        else
            node.Parent.Left = temp;
        temp.Right = node;
        if (node != null)
            node.Parent = temp;
    }

    // 中序遍历
    public void InOrderTraversal(Node node)
    {
        if (node != null)
        {
            InOrderTraversal(node.Left);
            Console.WriteLine(node.Data + " " + node.Color);
            InOrderTraversal(node.Right);
        }
    }
}


参考博客:https://www.jianshu.com/p/e136ec79235c

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

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

相关文章

【Unity3D日常开发】Unity3D中Quality的设置参考

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客 大家好&#xff0c;我是佛系工程师☆恬静的小魔龙☆&#xff0c;不定时更新Unity开发技巧&#xff0c;觉得有用记得一键三连哦。 一、前言 这篇文章就来讲一下Quality的设置&#xff08;Unity版本&#…

浪潮信息被Gartner评为全球文件存储标杆厂商

近日&#xff0c;国际权威研究机构 Gartner 正式发布《2023年存储和数据保护技术成熟度曲线报告》&#xff08;(Hype Cycle for Storage and Data Protection Technologies, 2023&#xff0c;以下简称“报告”&#xff09;&#xff0c;基于对市场应用的前瞻洞察和多年的技术精耕…

518抽奖软件,一键打印中奖名单的方法和用途

518抽奖软件简介 518抽奖软件&#xff0c;518我要发&#xff0c;超好用的年会抽奖软件&#xff0c;简约设计风格。 包含文字号码抽奖、照片抽奖两种模式&#xff0c;支持姓名抽奖、号码抽奖、数字抽奖、照片抽奖。(www.518cj.net) 一键打印中奖名单 主窗口上按 CtrlP 打开 {…

在关系型数据库中储存树形结构

adjacency list 邻接表显然是最简单的方式&#xff0c;也是在实践中经常用到的。其储存节点以及直接父节点来进行储存树形结构 邻接表结构简单&#xff0c;查询修改节点的直接父节点都很容易。然而如果返回父节点下的所有节点之类的跨层操作那就很麻烦了&#xff0c;需要频繁…

matlab实现杨氏双缝干涉实验可视化界面

关于杨氏双缝干涉实验的条纹光强理论推导和matlab绘图可以参考下面的链接&#xff1a;杨氏双缝干涉实验matlab实现 接下来利用GUI实现可视化界面。 一、GUI GUIDE简介 1、在命令行窗口输入小写的guide可以自动弹出fig窗口。 2、界面的左侧是常用的工具&#xff0c;鼠标悬停…

利用串口示波器调试PID参数

PID调试最麻烦的是参数调整&#xff0c;需要花费大量时间&#xff0c;如果每调整一次都要修改代码重新编译烧录&#xff0c;效率很低&#xff0c;推荐串口示波器与rt-thead finsh进行调试 推荐使用FireWater数据引擎 定时上报数据&#xff0c;rt_kprintf不支持浮点数据打印&a…

从零开始之了解电机及其控制(6)六步换向法

引导&#xff1a;六步换向的本质是&#xff1f; 因为无刷电机有三根线&#xff0c;而H桥可以将负载连接到正电压或者地&#xff0c;于是用三对MOS管组成的H桥驱动电机&#xff0c;称为半桥驱动。 无刷电机的优点如下&#xff1a; 首先&#xff0c;由于所有三个电机相位都通过…

xcode15下载ios17模拟器失败

升级到xcode15后需要安装ios17模拟器 但是在下载过程中会遇到报错 如下图这种 网上搜索了一下发现有人遇到过无法下载的问题&#xff0c;并且在apple官网也有人提出类似问题 https://developer.apple.com/forums/thread/737648 解决方案就是从https://developer.apple.com/do…

linux提权秘籍

Linux 提权总结 一、常用基础 1、自定义可执行文件(Custom Executable) 可能有某些根进程执行另一个可以控制的进程。在这些情况下&#xff0c;以下C代码一旦编译&#xff0c;将生成一个作为根运行的sbashell&#xff1a; int main() { setuid(0);system("/bin/bash -p…

MapBox GL JS出现“Unimplemented type: 7”问题的解决办法

Mapbox GL JS在矢量瓦片的渲染方面有独特的优势&#xff0c;可以支持动态的样式&#xff0c;支持字体切片&#xff0c;快速加载各种字体。使用起来十分方便&#xff0c;但是在很长的一段时间内&#xff0c;经常遇到出现大量“Unimplemented type: 7”的控制台错误提示&#xff…

Web自动化测试 —— headless无头浏览器!

一、Options概述 是一个配置浏览器启动的选项类&#xff0c;用于自定义和配置Driver会话常见使用场景&#xff1a; 设置无头模式:不会显示调用浏览器&#xff0c;避免人为干扰的问题。设置调试模式:调试自动化测试代码&#xff08;浏览器复用&#xff09; 二、添加启动配置 添…

丰田 Auris 混动车电池冷却系统异常

故障现象 一辆丰田 Auris 混合动力车行驶时&#xff0c;混合动力车警告灯亮起。这辆车被改装成监控用车&#xff0c;车厢内到处都装有敏感的录音设备。 为了不被下面的情况所影响&#xff0c;我们从混合动力控制单元&#xff08;HCU&#xff09;中提取了故障代码 P0A82-123。混…

Multisim14.0仿真(二十四)基于LM555定时器的施密特触发器

一、仿真原理图&#xff1a; 二、仿真效果图&#xff1a;

【数据结构——单链表】本篇文章通过图文结合的方式能让你轻松的掌握单链表

链表的概念及结构 有了顺序表为什么还会出现链表呢&#xff1f; 链表和数组类似&#xff0c;但是功能比数组强大的多&#xff0c;数组的空间是固定的&#xff0c;在定义数组的时候空间大小就已经固定了&#xff0c;在使用时有可能会造成空间的浪费或者面临空间不够的风险&…

2023年建筑架子工(建筑特殊工种)证考试题库及建筑架子工(建筑特殊工种)试题解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年建筑架子工(建筑特殊工种)证考试题库及建筑架子工(建筑特殊工种)试题解析是安全生产模拟考试一点通结合&#xff08;安监局&#xff09;特种作业人员操作证考试大纲和&#xff08;质检局&#xff09;特种设备作…

第九章 内存分区模型

C程序在执行时&#xff0c;将内存大方向划分为4个区域 代码区&#xff1a;存放函数体的二进制代码&#xff0c;由操作系统进行管理的 全局区&#xff1a;存放全局变量和静态变量以及常量 栈区&#xff1a;由编译器自动分配释放, 存放函数的参数值,局部变量等 堆区&#xff1…

【NLP的Python库(04/4)】:Flair

一、说明 Flair是一个现代的NLP库。从文本处理到文档语义&#xff0c;支持所有核心 NLP 任务。Flair使用现代转换器神经网络模型来完成多项任务&#xff0c;并结合了其他Python库&#xff0c;可以选择特定的模型。其清晰的API和注释文本的数据结构&#xff0c;以及多语言支持&a…

FPGA project : uart232_ram_vga

重点学习&#xff1a; 本实验重点学习了双口ram解决多bit跨时钟域同步处理的问题。 其实signal port ram&#xff0c;它的输入口和输出口分别用不同的时钟&#xff0c;也可以解决这个问题。 让我意识到的比较重要的事情&#xff1a; 1&#xff0c;代码设计中&#xff0c;一…

VEX —— Functions|Measure

目录 distance —— 返回两点间距离 distance2 —— 返回两点间距离平方 surfacedist —— 查找点到点组的距离&#xff08;沿几何体表面&#xff09; xyzdist —— 查找点到表面最近点的距离 uvdist —— 在uv空间查找uv坐标到几何体的距离 planepointdistance —— 计算…

【免费】2023云栖大会门票开抢啦!数量有限,先到先得!

&#x1f3ab; 报名方式&#xff1a;点击链接即可免费报名&#xff01; &#x1f517; 2023云栖大会-领票页 &#x1f4c5; 10月31日-11月2日&#xff0c;让我们齐聚云栖小镇&#xff01;