4. 树(二叉树、二叉查找树/二叉排序树/二叉搜索树、平衡二叉树、平衡二叉B树/红黑树)

    • 1. 二叉树
      • 1.1 概述
      • 1.2 特点
      • 1.3 二叉树遍历方式
        • 1.3.1 前序遍历(先序遍历)
        • 1.3.2 中序遍历
        • 1.3.3 后序遍历
        • 1.3.4 层序遍历
    • 2. 二叉查找树(二叉排序树、二叉搜索树)
      • 2.1 概述
      • 2.2 特点
    • 3. 平衡二叉树
      • 3.1 概述
      • 3.2 特点
      • 3.3 旋转
        • 3.3.1 左旋
        • 3.3.2 右旋
      • 3.4 平衡二叉树旋转的四种情况
        • 3.4.1 左左
        • 3.4.2 左右
        • 3.4.3 右右
        • 3.4.4 右左
    • 4. 红黑树(平衡二叉B树)
      • 4.1 概述
      • 4.2 特点
      • 4.3 规则
      • 4.4 添加节点

本文章里的部分照片来源于网络,特此声明,侵权联系删除!

								二叉树
								  |
								  | (由于二叉树存入的数据是无规则的)
								  |
					二叉查找树(二叉排序树、二叉搜索树)  
								  |
								  |	(由于二叉做查找树的两条子树的高度可能相差太大)
								  |
							  平衡二叉树	
							      |
								  |	(由于平衡二叉树添加数据可能需要旋转,浪费时间)
								  |
					     红黑树(平衡二叉B树)			    

1. 二叉树

1.1 概述

二叉树是一种常见的树状数据结构,由节点组成,每个节点最多有两个子节点,分别称为左子节点和右子节点。

  • 二叉树中,任意一个节点的度要小于等于2

  • 左子节点的值小于或等于当前节点的值

  • 右子节点的值大于当前节点的值。

  • 二叉树可以为空树,也可以只有一个根节点。

节点内部结构:

在这里插入图片描述

二叉树结构图:

在这里插入图片描述

1.2 特点

二叉树是一种常见的树状数据结构,它由节点组成,每个节点最多有两个子节点。

具有以下特点:

  1. 根节点:树的顶部节点,没有父节点。

  2. 叶子节点:没有子节点的节点。

  3. 左子节点和右子节点:一个节点只能有最多两个子节点,其中一个是左子节点,另一个是右子节点。

  4. 子树:每个节点都可以作为根节点,形成一颗子树。

  5. 深度:树中节点的最大层次数。

  6. 高度:树中节点的最大深度。

1.3 二叉树遍历方式

1.3.1 前序遍历(先序遍历)

前序遍历(先序遍历): 从根节点开始,然后按照当前节点,左子结点,右子节点的顺序遍历

前序遍历是二叉树遍历的一种方式,也被称为先序遍历。

在前序遍历中,先访问根节点,然后按照先左后右的顺序继续遍历左子树和右子树。

前序遍历的步骤

  1. 访问当前节点。

  2. 递归地前序遍历左子树。

  3. 递归地前序遍历右子树。

举个例子,考虑如下的二叉树:

     A
   /   \
  B     C
 / \   / \
D   E F   G

通过前序遍历,节点的访问顺序将会是:A - B - D - E - C - F - G。具体操作如下:

  1. 访问节点 A。
  2. 递归前序遍历左子树,访问节点 B。
  3. 递归前序遍历左子树,访问节点 D。
  4. 左子树为空,返回到节点 B。
  5. 递归前序遍历右子树,访问节点 E。
  6. 右子树为空,返回到节点 B。
  7. 返回到节点 A。
  8. 递归前序遍历右子树,访问节点 C。
  9. 递归前序遍历左子树,访问节点 F。
  10. 左子树为空,返回到节点 C。
  11. 递归前序遍历右子树,访问节点 G。
  12. 右子树为空,返回到节点 C。

前序遍历的结果是:A - B - D - E - C - F - G。

1.3.2 中序遍历

中序遍历:从最左边的子节点开始,然后按照左子结点,当前节点,右子节点的顺序遍历

中序遍历是二叉树遍历的一种方式。

在中序遍历中,先访问左子树,然后访问根节点,最后访问右子树。

中序遍历的步骤

  1. 递归地中序遍历左子树。

  2. 访问当前节点。

  3. 递归地中序遍历右子树。

举个例子,考虑如下的二叉树:

     A
   /   \
  B     C
 / \   / \
D   E F   G

通过中序遍历,节点的访问顺序将会是:D - B - E - A - F - C - G。具体操作如下:

  1. 递归中序遍历左子树,访问节点 D。
  2. 左子树为空,返回到节点 B。
  3. 中序遍历访问节点 B。
  4. 递归中序遍历左子树,访问节点 E。
  5. 左子树为空,返回到节点 B。
  6. 返回到节点 A。
  7. 递归中序遍历右子树,访问节点 F。
  8. 中序遍历访问节点 C。
  9. 递归中序遍历左子树,访问节点 G。
  10. 左子树为空,返回到节点 C。

中序遍历的结果是:D - B - E - A - F - C - G。

1.3.3 后序遍历

后序遍历:从最左边的子节点开始,然后按照左子结点,右子节点,当前节点的顺序遍历

后序遍历是二叉树遍历的一种方式。

在后序遍历中,先访问左子树,然后访问右子树,最后访问根节点。

后序遍历的步骤

  1. 递归地后序遍历左子树。

  2. 递归地后序遍历右子树。

  3. 访问当前节点。

举个例子,考虑如下的二叉树:

     A
   /   \
  B     C
 / \   / \
D   E F   G

通过后序遍历,节点的访问顺序将会是:D - E - B - F - G - C - A。具体操作如下:

  1. 递归后序遍历左子树,访问节点 D。
  2. 左子树为空,返回到节点 B。
  3. 递归后序遍历右子树,访问节点 E。
  4. 右子树为空,返回到节点 B。
  5. 后序遍历访问节点 B。
  6. 递归后序遍历左子树,访问节点 F。
  7. 左子树为空,返回到节点 C。
  8. 递归后序遍历右子树,访问节点 G。
  9. 右子树为空,返回到节点 C。
  10. 后序遍历访问节点 C。
  11. 返回到节点 A。
  12. 后序遍历访问节点 A。

后序遍历的结果是:D - E - B - F - G - C - A。

1.3.4 层序遍历

层序遍历:从根节点开始一层一层的遍历。

层序遍历是二叉树遍历的一种方式。

在层序遍历中,按照从上到下、从左到右的顺序逐层访问节点。

层序遍历的步骤

  1. 将根节点入队。

  2. 循环执行以下操作直到队列为空:

    • 出队一个节点,访问该节点。

    • 如果该节点有左子节点,则将左子节点入队。

    • 如果该节点有右子节点,则将右子节点入队。

举个例子,考虑如下的二叉树:

     A
   /   \
  B     C
 / \   / \
D   E F   G

通过层序遍历,节点的访问顺序将会是:A - B - C - D - E - F - G。具体操作如下:

  1. 将根节点 A 入队。
  2. 出队节点 A,并访问节点 A。
  3. 将左子节点 B 入队。
  4. 将右子节点 C 入队。
  5. 出队节点 B,并访问节点 B。
  6. 将左子节点 D 入队。
  7. 将右子节点 E 入队。
  8. 出队节点 C,并访问节点 C。
  9. 将左子节点 F 入队。
  10. 将右子节点 G 入队。
  11. 出队节点 D,并访问节点 D。
  12. 出队节点 E,并访问节点 E。
  13. 出队节点 F,并访问节点 F。
  14. 出队节点 G,并访问节点 G。

层序遍历的结果是:A - B - C - D - E - F - G。

2. 二叉查找树(二叉排序树、二叉搜索树)

2.1 概述

二叉查找树(Binary Search Tree,BST)是一种特殊的二叉树结构,在这种树中,每个节点的值都大于其左子树中的任何节点的值,且小于其右子树中的任何节点的值。这使得二叉查找树具有高效的搜索和插入操作。

  • 二叉查找树,又称二叉排序树或者二叉搜索树

2.2 特点

  • 二叉查找树的特点

    • 每一个节点上最多有两个子节点

    • 左子树上所有节点的值都小于根节点的值

    • 右子树上所有节点的值都大于根节点的值

    • 没有重复的节点值。

  • 二叉查找树结构图

    在这里插入图片描述

  • 二叉查找树和二叉树对比结构图

    在这里插入图片描述

  • 二叉查找树添加节点规则

    • 小的存左边

    • 大的存右边

    • 一样的不存

    在这里插入图片描述

3. 平衡二叉树

3.1 概述

平衡二叉树(Balanced Binary Tree),也称为 AVL 树(平衡二叉搜索树),是一种特殊的二叉查找树,它的特点是每个节点的左子树和右子树的高度差不超过1。

平衡二叉树的设计目的是为了保持二叉树的平衡性,以提高查找、插入和删除操作的效率。普通的二叉查找树在某些情况下可能会退化为链表,导致操作的时间复杂度从平均情况下的 O(logn) 变成最坏情况下的 O(n),而平衡二叉树的高度始终保持在 logn 的范围内,保证了操作的高效性。

在平衡二叉树中,每个节点都有一个平衡因子(balance factor),定义为左子树的高度减去右子树的高度。平衡因子可以使平衡二叉树保持平衡。当插入或删除一个节点时,可能会破坏平衡,此时需要通过旋转操作来调整树的结构,使其重新满足平衡性的要求。

3.2 特点

  • 平衡二叉树的特点

    • 二叉树左右两个子树的高度差不超过1

    • 任意节点的左右两个子树都是一颗平衡二叉树

3.3 旋转

  • 旋转触发时机:当添加一个节点之后,该树不再是一颗平衡二叉树
3.3.1 左旋
  • 就是将根节点的右侧往左拉,原先的右子节点变成新的父节点,并把多余的左子节点出让,给已经降级的根节点当右子节点

    在这里插入图片描述
    在这里插入图片描述

3.3.2 右旋
  • 就是将根节点的左侧往右拉,左子节点变成了新的父节点,并把多余的右子节点出让,给已经降级根节点当左子节点

    在这里插入图片描述
    在这里插入图片描述

3.4 平衡二叉树旋转的四种情况

3.4.1 左左
  • 左左: 当根节点左子树的左子树有节点插入,导致二叉树不平衡

    • 如何旋转: 直接对整体进行右旋即可

    在这里插入图片描述

3.4.2 左右
  • 左右: 当根节点左子树的右子树有节点插入,导致二叉树不平衡

    • 如何旋转: 先在左子树对应的节点位置进行左旋,在对整体进行右旋

      在这里插入图片描述

3.4.3 右右
  • 右右: 当根节点右子树的右子树有节点插入,导致二叉树不平衡

    • 如何旋转: 直接对整体进行左旋即可
      在这里插入图片描述
3.4.4 右左
  • 右左:当根节点右子树的左子树有节点插入,导致二叉树不平衡

    • 如何旋转: 先在右子树对应的节点位置进行右旋,在对整体进行左旋

      在这里插入图片描述

  • 平衡二叉树和二叉查找树对比结构图
    在这里插入图片描述

4. 红黑树(平衡二叉B树)

4.1 概述

红黑树(Red-Black Tree)是一种自平衡的二叉查找树,它在进行插入和删除等操作时能够自动调整树的结构,以保持树的平衡性。红黑树的设计目的是在维持平衡的同时提供较高的插入、删除和查找效率。

红黑树的名称来源于每个节点上的一个额外的属性,即节点的颜色,可以是红色或黑色。

红黑树的插入和删除操作都会涉及到节点的颜色变化和旋转操作,通过这些操作来保持树的平衡性。相较于其他平衡二叉树如 AVL 树,红黑树的实现相对简单,并且对于插入和删除操作的限制较少,因此在实际应用中更为常见。

节点内部结构:
在这里插入图片描述

4.2 特点

  • 红黑树的特点

    • 平衡二叉B树

    • 每一个节点可以是红或者黑

    • 红黑树不是高度平衡的,它的平衡是通过"自己的红黑规则"进行实现的

4.3 规则

  • 红黑树的红黑规则:

    1. 每一个节点或是红色的,或者是黑色的

    2. 根节点必须是黑色

    3. 如果一个节点没有子节点或者父节点,则该节点相应的指针属性值为Nil,这些Nil视为叶节点,每个叶节点(Nil)是黑色的

    4. 如果某一个节点是红色,那么它的子节点必须是黑色(不能出现两个红色节点相连 的情况)

    5. 对每一个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点

      在这里插入图片描述

  • 红黑树添加节点的默认颜色

    • 添加节点时,默认为红色,效率高

      在这里插入图片描述

4.4 添加节点

  • 红黑树添加节点后保持红黑规则方法:

    • 根节点位置
      • 直接变为黑色
    • 非根节点位置
      • 父节点为黑色
        • 不需要任何操作,默认红色即可
      • 父节点为红色
        • 叔叔节点为红色
          1. 将"父节点"设为黑色,将"叔叔节点"设为黑色

          2. 将"祖父节点"设为红色

          3. 如果"祖父节点"为根节点,则将根节点再次变成黑色

        • 叔叔节点为黑色
          1. 将"父节点"设为黑色

          2. 将"祖父节点"设为红色

          3. 以"祖父节点"为支点进行旋转

在这里插入图片描述

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

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

相关文章

Quartus IP 之mif与hex文件创建与使用

一、mif与hex概述 ROM IP的数据需要满足断电不丢失的要求,ROM IP数据的文件格式一般有三种文件格式:.mif、.hex、.coe,Xilinx与Intel Altera支持的ROM IP数据文件格式如下: Xilinx与Altera支持的ROM文件格式 Alterahex、mifAM&am…

JS第二天、原型、原型链、正则

☆☆☆☆ 什么是原型? 构造函数的prototype 就是原型 专门保存所有子对象共有属性和方法的对象一个对象的原型就是它的构造函数的prototype属性的值。prototype是哪来的?所有的函数都有一个prototype属性当函数被创建的时候,prototype属性…

项目02《游戏-08-开发》Unity3D

基于 项目02《游戏-07-开发》Unity3D , 本次任务做物品相互与详情的功能, 首先要做 点击相应, 接下来用接口实现点击相应事件,具体到代码中,我们找到需要响应鼠标事件的对象, 双击PackageCell…

食堂预约系统

文章目录 前言​部分沟通内容技术点小程序功能部分代码段功能图 商家管理系统功能说明功能图登录页面商家管理页面 食品管理订单管理其他功能 结束语 前言​ 最近,接了个小项目——学校食堂预约取餐系统。 具体需求如下图: 部分沟通内容 技术点 系统…

C++:模板初阶

泛型编程 泛型编程:编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。 函数模板 函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。…

百面嵌入式专栏(面试题)网络编程面试题

沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇我们将介绍网络编程面试题 。 1、什么是IO多路复用 I/O多路复用的本质是使用select,poll或者epoll函数,挂起进程,当一个或者多个I/O事件发生之后,将控制返回给用户进程。以服务器编程为例,传统的多进程(多线程…

antv/x6 边添加鼠标悬浮高亮和删除功能

antv/x6 边添加鼠标悬浮高亮和删除功能 效果添加悬浮效果和删除工具取消悬浮效果边删除后的回调函数 效果 添加悬浮效果和删除工具 this.graph.on(edge:mouseenter, ({ cell }) > {let cellId cell.store.data.source.celllet sourceCell _this.graph.getCellById(cellId…

绝地求生:盘点游戏内七款真人脸模,你最喜欢哪款?

从27.1版本更新后,游戏内上线了荣都地图代言人吴彦祖和李政宰的真人脸模,从此闲游盒的各位盒友灵魂搭配的资源库里又多了两位英俊脸庞,那么今天闲游盒来盘点一下游戏内上线的七款真人脸模,看看大家更喜欢哪款呢? 吴彦祖和李政宰 …

CSS-IN-JS

CSS-IN-JS 为什么会有CSS-IN-JS CSS-IN-JS是web项目中将CSS代码捆绑在JavaScript代码中的解决方案。 这种方案旨在解决CSS的局限性,例如缺乏动态功能,作用域和可移植性。 CSS-IN-JS介绍 1:CSS-IN-JS方案的优点: 让css代码拥…

【MySQL】DQL的总结和案例学习

🌈个人主页: Aileen_0v0 🔥热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​💫个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-VWRkWqFrRMi4uLRa {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

bert分类模型使用

使用 bert-bert-chinese 预训练模型去做分类任务,这里找了新闻分类数据,数据有 20w,来自https://github.com/649453932/Bert-Chinese-Text-Classification-Pytorch/tree/master/THUCNews 数据 20w ,18w 训练数据,1w 验…

挑战!贪吃蛇小游戏的实现(1)

引言 相信大家都玩过贪吃蛇这个游戏! 玩家控制一个不断移动的蛇形角色,在一个封闭空间内移动。随着时间推进,这个蛇形角色会逐渐增长,通常是通过吞食屏幕上出现的物品(如点或者其他标志)来实现。每当贪吃…

JQuery动态插入Bootstrap模态框(Modal)

这里所说的动态插入,是指用JS的append()方式追加元素内容,而不是静态写在HTML里面。 为什么会用到这种方式呢?比如登录框。有些网站在大部分页面都有登录按钮,如果是用Bootstrap的模态框调用的话,常规方式都是写在HTM…

目标检测及相关算法介绍

文章目录 目标检测介绍目标检测算法分类目标检测算法模型组成经典目标检测论文 目标检测介绍 目标检测是计算机视觉领域中的一项重要任务,旨在识别图像或视频中的特定对象的位置并将其与不同类别中的对象进行分类。与图像分类任务不同,目标检测不仅需要…

vue全家桶之状态管理Pinia

一、Pinia和Vuex的对比 1.什么是Pinia呢? Pinia(发音为/piːnjʌ/,如英语中的“peenya”)是最接近pia(西班牙语中的菠萝)的词; Pinia开始于大概2019年,最初是作为一个实验为Vue重新…

详解C++类和对象(上)

文章目录 写在前面1. 类的定义2. 类的访问限定符及封装2.1 类的访问限定符2.2 封装 3. 类的作用域4. 类的实例化5 类的对象大小的计算6. 类成员函数的this指针 写在前面 类和对象这一章节,分为上、中、下三篇文章进行拆分介绍的,本篇文章介绍了类和对象…

LabVIEW与EtherCAT实现风洞安全联锁及状态监测

LabVIEW与EtherCAT实现风洞安全联锁及状态监测 在现代风洞试验中,安全联锁与状态监测系统发挥着至关重要的作用,确保了试验过程的安全性与高效性。介绍了一套基于EtherCAT总线技术和LabVIEW软件开发的风洞安全联锁及状态监测系统。该系统通过实时、可靠…

C++后端开发之Sylar学习二:配置VSCode远程连接Ubuntu开发

C后端开发之Sylar学习二:配置VSCode远程连接Ubuntu开发 没错,我不能像大佬那样直接在Ubuntu上面用Vim手搓代码,只能在本地配置一下VSCode远程连接Ubuntu进行开发咯! 本篇主要是讲解了VSCode如何配置ssh连接Ubuntu,还有…

蓝桥杯每日一题-----数位dp练习

题目 链接 参考代码 写了两个,一个是很久以前写的,一个是最近刚写的,很久以前写的时候还不会数位dp所以写了比较详细的注释,这两个代码主要是设置了不同的记忆数组,通过这两个代码可以理解记忆数组设置的灵活性。 im…

UE4运用C++和框架开发坦克大战教程笔记(十七)(第51~54集)

UE4运用C和框架开发坦克大战教程笔记(十七)(第51~54集) 51. UI 框架介绍UE4 使用 UI 所面临的问题以及解决思路关于即将编写的 UI 框架的思维导图 52. 管理类与面板类53. 预加载与直接加载54. UI 首次进入界面 51. UI 框架介绍 U…
最新文章