news 2025/12/24 19:12:27

数据结构:二叉排序树,平衡二叉树,红黑树的介绍

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
数据结构:二叉排序树,平衡二叉树,红黑树的介绍

一.二叉排序树

二叉排序树的定义是任意一个父节点的值,大于其左子树节点的值,小于其右子树节点的值。

以下是两个例子:

(1)数组:5,3,1,4,8,9,7

它的二叉排序树是这样的:

它的时间复杂度是O(logn)。

(2)数组:1,2,3

它的二叉排序树是这样的:

它的时间复杂度是O(n)。

由此可见,两种情况下的二叉排序树的时间复杂度不同,因此,二叉排序树是不稳定的

当树的结构完全平衡时(如红黑树),节点数 n 与高度 h 的关系为h = logn。此时核心操作的时间复杂度为O(log n),这是二叉排序树的最优性能。
当节点按升序或降序插入时,二叉排序树会退化为一条单链(每个节点只有左子树或只有右子树)。此时树的高度h = n,核心操作的时间复杂度退化为O(n)

为了解决这种不平衡的现象,引入了一种更先进的树,名为平衡二叉树。


二.平衡二叉树

平衡二叉树在排序二叉树的基础上,要求左右子树高度差的绝对值不能超过 1(小于等于 1)。

如果这个树不平衡了,我们应该怎么调节?于是引入了4种平衡化调整策略。

(1)LL型

这是调节前的树:

这是调节后的树:

技巧:让不平衡节点朝着造成不平衡的节点走两步,盯着不平衡主链,让中间节点成为新的父节点,其余节点按照顺序进行插入。

(2)RR型

这是调节前的树:

这是调节后的树:

整体方法和LL型类似。

(3)LR型

这是调节前的树:

这是调节后的树:

技巧:

还是先让不平衡节点朝着造成不平衡的节点走两步,

然后盯着不平衡主链,采用两步旋转法:

第一步:后二整体旋转(把造成不平衡的点和它的父节点调换顺序,并变成LL/RR型

第二步:采用LL/RR旋转

(4)RL型

这是调节前的树:

后二整体旋转之后的树:

这是调节后的树:

整体和LR型类似。

其实,平衡二叉树也是有缺点的,它过分追求时间复杂度的完美,导致旋转过程会消耗大量的计算机资源

于是引入了一个性能更好的树,名为红黑树。


三.红黑树

在介绍红黑树之前,要先了解一下2-3-4树(4阶B树),因为2-3-4树与红黑树是等价的数据结构,它们之间可以相互转换。

(1)2-3-4树的特点与插入操作

2-3-4树每种节点的结构:

特性:每个节点的关键字都是有序排列的,且左子树的所有关键字小于根节点关键字,右子树的所有关键字大于根节点关键字。所有叶子节点都在同一层,保证了树的高度平衡。

插入操作:首先从根节点开始查找插入位置,找到合适的叶子节点后插入新关键字。如果插入后该节点的关键字数量超过 3 个(即成为 4 - 节点),则需要进行分裂操作。将 4 - 节点中间的关键字提升到父节点,左右两边的关键字分别形成两个新节点。如果父节点也因此变得满了(成为 4 - 节点),则需要递归地对父节点进行分裂操作。

(2)2-3-4树到红黑树的转换

首先我们先了解一下2-3-4树与红黑树各种节点的对应样式:

下图是一个2-3-4树:

然后找到各节点对应的红黑树样式,2节点对应一个黑节点,3节点对应父节点是黑节点,下面接一个红结点,4节点对应父节点是黑节点,下面左右节点都是红结点

调整好之后如下图所示:

(每个最下方的节点下面都有一个黑色的叶子结点,图中没有画出来)

(3)红黑树的特点

1.红黑树的节点颜色不是红色就是黑色的。
2.根节点一定是黑色的。
3.叶子节点也是黑色的(上面那张图每个最下方的节点下面都有一个黑色的叶子结点,图中没有画出来)。
4.如果一个节点是红色的,那么他的子节点一定是黑色的。
5.从根节点出发到任意的一个叶子节点,所走过的路径上黑色节点的数目是相同的。

从特点中还可以得出一个结论:红黑树当中最长的链条不会超过最短链条的 2 倍。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/13 23:43:13

Go语言变量

Go变量声明的核心机制 静态类型语言要求变量在使用前必须声明,明确内存边界。Go作为静态语言,通过变量声明实现这一机制: 变量绑定特定内存区域,类型信息确定操作边界声明形式为:var 变量名 类型 值未显式初始化时自动…

作者头像 李华
网站建设 2025/12/13 23:42:00

【高可用系统架构】

系统高可用实现手段 冗余与无单点设计 部署关键节点时避免单点故障,例如负载均衡采用双节点Keepalived方案(如Nginx/HAProxy/LVS),通过虚拟IP实现故障自动切换。网络通信配置多线路(如移动电信双线)&#x…

作者头像 李华
网站建设 2025/12/13 23:41:04

高频软件测试基础面试题

在软件测试的面试过程中,面试官会问些基础的软件测试知识,下面为大家整理了一些高频软件测试面试必备的基础题,拿走不谢~ 一、什么是软件测试 为了发现程序中的错误而执行程序的过程。 二、软件测试的原则 1、完全测试程序是不可能的 2、…

作者头像 李华
网站建设 2025/12/13 23:40:04

如何准确判断json文件并且拿到我想要的信息

写在前面,自从发现拿到json解析后的文件中有我们想要的信息后,我稍微有点迷上这种方法,但是拿到内容后要怎么拿到想要的信息呢,字典列表相互嵌套,我头都晕了方法:首先就是把json解析后的文本保存成.json的形…

作者头像 李华
网站建设 2025/12/13 23:39:12

C++进阶技巧:如何在同一对象中存储左值或右值

一、背景C 代码似乎经常出现一个问题:如果该值可以来自左值或右值,则对象如何跟踪该值?即如果保留该值作为引用,那么就无法绑定到临时对象。如果将其保留为一个值,那么当它从左值初始化时,会产生不必要的副…

作者头像 李华
网站建设 2025/12/13 23:38:16

【Arduino Uno】数码管模拟值实验

目录 一.1位数码管模拟值1.共阳极数码管实验效果2.共阳极与共阴极数码管原理与构造数码管内部构造 3.需要的组件4.共阳极数码管接线图5.共阳极代码阳极代码调换为阴极 6.优化代码补充说明 7.总结 一.1位数码管模拟值 1.共阳极数码管实验效果 数码管模拟值实验共阳极2.共阳极与…

作者头像 李华