Python - 深夜数据结构与算法之 AVL 树 红黑树

目录

一.引言

二.高级树的简介

1.树

2.二叉树

3.二叉搜索树

4.平衡二叉树

三.AVL 树

◆ 插入节点

◆ 左旋

◆ 右旋

◆ 左右旋

◆ 右左旋

◆ 一般形式

◆ 实际操作

◆ 总结

四.红黑树

◆ 概念

◆ 示例

◆ 对比

五.总结


一.引言

前面我们介绍了二叉树、二叉搜索树、多叉树等基础的树形结构,本文扩展一些新的树类型,例如 AVL 树、红黑树、B 树等等,完善一下整个框架内树的的概念。

二.高级树的简介

1.树

树,这里就不多重复了,包括根节点、左右子节点,分为多个层级的扩散的结构,因为其树形的结构天然的适合使用递归的方法进行遍历与处理。

2.二叉树

只有左右分叉的树即为二叉树, 二叉树主要掌握其三种遍历方式。

- 前序 Pre-order 根-左-右

- 中序 In-Order 左-根-右

- 后序 Post-Order 左-右-根

3.二叉搜索树

通过对数据进行有序编排,二叉搜索树将 o(n) 的搜索复杂度缩减为 o(log2n),其特点:

左子树所有节点小于根节点

右子树所有节点大于根节点

需要注意,二叉搜索树的中序遍历是升序排列。 

◆ 节点查找

只需要与根节点比较即可,小于根节点到左子树,大于2根节点到右子树。 可以看到其查询的时间复杂度就是树的深度即 Level。

◆ 极端情况

当我们构建二叉搜索树时不注意树的结构或者平衡时,其容易出现如上图所示的极端情况,此时二叉树退化为链表,其搜索复杂度也恢复至 o(n)。

4.平衡二叉树

上面这种情况,最简单的平衡方法就是从中间把棍子打断,然后对于左右的棍子依次打断,直到平衡,但是实际情况下我们不会等树发展到这种棍子的状态才进行调整,我们一般在每一步插入元素的时候都会查看当前树是否平衡,并对其进行平衡化的操作。下面我们就了解几种常见的平衡二叉树。

三.AVL 树

AVL 树命名来源于其发明者,其在树中引入了平衡因子即 Balance Factor,该因子的计算为 左子树高度 - 右子树高度 或者 右子树高度 - 左子树高度,因此其值的范围控制在 -1、0、1。这里是高度而不是节点数的原因是二叉树的搜索时间复杂度与其深度即 Level 有关,而不是节点个数 (考虑棍子的极端情况)。当检测到数非平衡时,其会通过四种旋转操作使树达到平衡。

以上面的二叉树为例,每一个节点的平衡因子都基于其左右子树的深度差计算,以 J 为例,右子树深度即 Level 为 4,而左子树的深度为 3,从而其值 = 4 - 3 = 1。 而所有叶子节点左右子树都为 0,所以其值为 0。上面这个树的平衡因子范围在 [-1, 1],因而其是一颗严格意义上平衡的AVL 树,因此保持一个树的平衡因子在 [-1,1] 范围内,其就是一颗平衡二叉搜索树。

◆ 插入节点

14 增加后平衡因子在 [-1,1] 范围内,因此无需调整。 

3 增加后根节点与第一个左节点的平衡因子变为 -2,此时平衡树被打破,需要使用旋转操作进行 reblance,共有四种旋转方式:

◆ 左旋

右右子树的情况,需要进行一次左旋调整为 AVL树。 A < B < C,所以 A B C 有效。

◆ 右旋

左左子树的情况下,依次右旋调整为 AVL 树。 A > B > C,所以 C B A 有效。

◆ 左右旋

左右子树即先一个单独左,再一个单独右,此时满足 A > B && C > B && A > C,结合在一起就是 A > C > B,所以可以先左旋 BC 并调换位置调整为 A > C > B 的左左子树,再右旋得到 B C A。

  

◆ 右左旋

B > A,B > C,C > A => B > C > A,所以可以切换为右右子树 A C B,再一次左旋即可。 

◆ 一般形式

上面介绍了单节点的四种旋转方式,实际场景带子树的情况比较多,上面是几种通用的旋转方法。 我们再从头捋一遍 AVL 树,首先树的查询是基于其深度 Level 来的,所以通过引入平衡因子就能够获得高度差从而衡量一个树是否平衡,当超过1不平衡时,我们可以通过旋转进行 rebalance,此时从单节点推广至多节点,AVL 树的情况大致就这样。

◆ 实际操作

下面基于真实的二叉搜索树进行旋转操作。

- 左左子树

红框所在部分为左左子树,根据一般形式,我们需要把 Pivot = 5 提上去,再把 10 放下来,同时 Pivot 的 Right 挂到 root = 10 的  Left,就得到下面的结果,没理解的同学看一般形式再对应一下:

- 右左子树

红框部分为右左子树,参考上面一般方法, 进行右左旋,先将 15 换到 16,再把 16 改为 15.right,最后把 15 拿上去,9 改为 15.left 即可。

◆ 总结

AVL 树在满足平衡二叉搜索的情况下,每个 Node 都多余存储了一个平衡节点,因此其会有额外的存储负担,其次对于节点的增删,很容易使其成为非平衡的状态,从而频繁引发调整。 

四.红黑树

◆ 概念

上面的 AVL 树通过平衡因子维持整个搜索树的平衡,但是由于其因子范围太小 [-1,1] 导致这里调整的频率太高,从而影响了查询的效率,所以为了折中就推出了一些近似平衡二叉树,红黑树就是其中的代表。其允许左右子树之间的高度差在两倍以内,放宽了范围从而较少了调整的次数。

◆ 示例

上面提到五条性质,前三条比较 common,主要看后两条:

- 不能有相临接的两个红色节点

- 任一节点到其每个叶子的所有路径都包含相同数目的黑色节点 

Most Important:

从根到叶子的最长的可能路径不多于最短路径的两倍长。

◆ 对比

- AVL 树相比红黑树提供更快的查询效率,因为其更严格的平衡

- 红黑树提供了更快的插入和移除效率,因为 AVL 涉及到过多的旋转调整

- AVL 存储更多,因为其需要 int 存储节点平衡度,而红黑树只需要 bit 存储红或蓝即 0 或 1 

- 读多写少适合使用 AVL 树,而工程中二者兼顾,所以红黑树的使用更加普遍例如 map/multimap

五.总结

截止到目前,一些基础的搜索结构与算法我们也了解差不多了,从最基本的树形结构,到并查集、Trie 树、二叉树、完全二叉树、平衡树等等。由于 AVL 树和红黑树的实现相对复杂,所以我们主要掌握其思想以及对应的几种旋转操作即可,做到能够看懂说清。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

论文阅读 Self-Supervised Burst Super-Resolution

这是一篇 ICCV 2023 的文章&#xff0c;主要介绍的是用自监督的方式进行多帧超分的学习 Abstract 这篇文章介绍了一种基于自监督的学习方式来进行多帧超分的任务&#xff0c;这种方法只需要原始的带噪的低分辨率的图。它不需要利用模拟退化的方法来构造数据&#xff0c;而且模…

爬虫验证码分析

声明&#xff1a; 该文章为学习使用&#xff0c;严禁用于商业用途和非法用途&#xff0c;违者后果自负&#xff0c;由此产生的一切后果均与作者无关 本文只做简单的验证码分析&#xff0c;不涉及扣代码等逆向 一、常见得验证码平台 易盾&#xff1a;https://dun.163.com/pr…

重学Java 5 idea详细使用和运算符

慢点跑&#xff0c;前面的路不好走 ——24.1.14 一、IDEA的使用 1.idea的介绍 1.概述&#xff1a;开发工具 2.特点&#xff1a; a、idea是java写的&#xff0c;所以本地上必须有正确的jdk环境 b、idea自动保存 c、不用我们打开dos命令窗口执行javac和java命令 d、idea有强大的…

数据结构与算法教程,数据结构C语言版教程!(第四部分、字符串,数据结构中的串存储结构)一

第四部分、字符串&#xff0c;数据结构中的串存储结构 串存储结构&#xff0c;也就是存储字符串的数据结构。 很明显&#xff0c;字符串之间的逻辑关系也是“一对一”&#xff0c;用线性表的思维不难想出&#xff0c;串存储结构也有顺序存储和链式存储。 提到字符串&#xff…

Python 自学(八) 之模块

目录 1. import语句导入模块 P206 2. from ... import 语句导入模块 P207 3. 模块的搜索目录 sys.path P209 4. 以主程序的形式执行 __name__ P212 5. python中的包 P213 1. import语句导入模块 P206 同一目录下&…

【MATLAB】 SSA奇异谱分析信号分解算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~ 1 基本定义 SSA奇异谱分析&#xff08;Singular Spectrum Analysis&#xff09;是一种处理非线性时间序列数据的方法&#xff0c;可以对时间序列进行分析和预测。 它基于构造在时间序列上的特定矩阵的奇异值分解&#…

12AOP面向切面编程/GoF之代理模式

先看一个例子&#xff1a; 声明一个接口&#xff1a; // - * / 运算的标准接口! public interface Calculator {int add(int i, int j);int sub(int i, int j);int mul(int i, int j);int div(int i, int j); }实现该接口&#xff1a; package com.sunsplanter.prox…

编曲混音FL Studio21.2对电脑有什么配置要求

FL Studio 21是一款非常流行的音乐制作软件&#xff0c;它可以帮助音乐人和制作人创作出高质量的音乐作品。然而&#xff0c;为了保证软件的稳定性和流畅性&#xff0c;用户需要知道FL Studio 21对电脑的配置要求。本文将介绍FL Studio 21的配置要求&#xff0c;以帮助用户选择…

Open CV 图像处理基础:(七)学习 OpenCV 的图像增强和边缘检测功能

在Java中学习使用 OpenCV 的图像增强和边缘检测功能 目录 在Java中学习使用 OpenCV 的图像增强和边缘检测功能前言图像增强功能对比度调整&#xff08;Core.addWeighted()&#xff09;函数原型&#xff1a;参数说明&#xff1a;代码&#xff1a;示例 直方图均衡化&#xff08;I…

强化学习应用(五):基于Q-learning的物流配送路径规划研究(提供Python代码)

一、Q-learning算法简介 Q-learning是一种强化学习算法&#xff0c;用于解决基于马尔可夫决策过程&#xff08;MDP&#xff09;的问题。它通过学习一个值函数来指导智能体在环境中做出决策&#xff0c;以最大化累积奖励。 Q-learning算法的核心思想是使用一个Q值函数来估计每…

图形化编程:开启孩子创新思维的新途径

在科技日新月异的今天&#xff0c;编程已经成为了一项重要的技能。然而&#xff0c;对于孩子们来说&#xff0c;传统的编程语言可能会显得过于复杂和抽象。这时&#xff0c;图形化编程就显得尤为重要。那么&#xff0c;什么是图形化编程&#xff1f;它对孩子有什么帮助呢&#…

web前端算法简介之字典与哈希表

回顾 栈、队列 &#xff1a; 进、出 栈&#xff08;Stack&#xff09;&#xff1a; 栈的操作主要包括&#xff1a; 队列&#xff08;Queue&#xff09;&#xff1a; 队列的操作主要包括&#xff1a; 链表、数组 &#xff1a; 多个元素存储组成的 简述链表&#xff1a;数组&…

权责发生制和收付实现制

目录 一. 权责发生制(应记制)二. 收付实现制 \quad 一. 权责发生制(应记制) 应计制就是应该记入的意思 各项收入和费用的确认应当以“实际发生”&#xff08;归属期&#xff09;而不是以款项的实际收付作为记账的基础。 正是有会计期间假设&#xff0c;才有权责发生制和收付实…

Odrive 学习系列二:将烧录工具从ST-Link V2修改为JLink

一、背景: 通过观察odrive解压后的内容,可以看到在下面配置文件及makefile文件中的配置设置的均为openOCD + stlink v2,例如makefile中: # This is only a stub for various commands. # Tup is used for the actual compilation.BUILD_DIR = build FIRMWARE = $(BUILD_DI…

【软件测试学习笔记1】测试基础

1.软件测试的定义 软件的定义&#xff1a;控制计算机硬件工作的工具 软件的基本组成&#xff1a;页面客户端&#xff0c;代码服务器&#xff0c;数据服务器 软件产生的过程&#xff1a;需求产生&#xff08;产品经理&#xff09;&#xff0c;需求文档&#xff0c;设计效果图…

工业级安卓PDA超高频读写器手持掌上电脑,RFID电子标签读写器

掌上电脑&#xff0c;又称为PDA。工业级PDA的特点就是坚固&#xff0c;耐用&#xff0c;可以用在很多环境比较恶劣的地方。 随着技术的不断发展&#xff0c;加快了数字化发展趋势&#xff0c;RFID技术就是RFID射频识别及技术&#xff0c;作为一种新兴的非接触式的自动识别技术&…

【网络工程师】NAT与动态路由

一、NAT网络地址转换 1、NAT&#xff1a;Network Address Translations 网络地址转换 2、ip地址问题&#xff1a;ipv4地址严重不够用了&#xff08;A、B、C类可以使用 D组播 E科研&#xff09; 3、解决&#xff1a;把IP地址分为了公网IP和私网IP 公网IP只能在公网上使用 私网…

探索数据之美:深入Seaborn的数据可视化艺术与技巧【第26篇—python:Seaborn】

文章目录 1. 引言2. Seaborn基础2.1 安装和环境设置2.2 常用数据可视化函数2.3 设置样式和颜色主题 3. 数据准备与导入3.1 使用Pandas库加载和处理数据3.2 数据清理和缺失值处理 4. Seaborn中的常见图表4.1 折线图和散点图&#xff1a;展示趋势和变量关系4.2 条形图和箱线图&am…

把模板作为元函数参数传递。

C模板元编程是一种典型的函数式编程&#xff0c;函数在整个编程体系中处于核心的地位。 这里的函数与一般C程序中定义的函数有所区别&#xff0c;其更接近数学意义上的函 数——是无副作用的映射或变换&#xff1a;在输入相同的前提下&#xff0c;多次调用同一个函数&…

命令行登录Mysql的详细讲解

目录 前言1. 本地登录2. 远程登录3. 拓展 前言 对于命令行登录Mysql一般都是用mysql -u root -p 但对于如何远程登陆&#xff0c;一直其他的参数还是有些盲区&#xff0c;对此总结科普 对于登录过程中出现的问题&#xff0c;可看我之前的文章&#xff1a; 服务器 出现ERROR …