数据结构之树与二叉树

华子目录

  • 1.树和二叉树的定义
    • 1.1树的定义
    • 1.2树的基本术语
    • 1.3线性结构和树结构
    • 1.4二叉树的定义
  • 2.二叉树的性质和存储结构
    • 2.1二叉树的性质
    • 2.2二叉树的存储结构
      • 2.2.1顺序存储
      • 2.2.2链式存储
    • 2.3遍历二叉树
    • 2.4大作业:二叉树的基本操作
      • 2.4.1代码思路(仅供参考,思路不限):
      • 2.4.2代码实践(递归写法)

1.树和二叉树的定义

1.1树的定义

nn≥0)个结点有限集或为空树n=0);或为非空树,对于非空树T

  • 有且仅有一个称之为结点
  • 根结点以外的其余结点可分为mm>0)个互不相交有限集T₁,T₂,…,Tm,其中每一个结点本身又是一棵树,并且成为子树

在这里插入图片描述
图 1(A) 是使用树结构存储的集合{A,B,C,D,E,F,G,H,I,J,K,L,M}示意图。对于数据A来说,和数据B、C、D有关系;对于数据B来说,和E、F有关系。这就是“一对多”的关系。将具有“一对多”关系的集合中的数据元素按照图 1(A)的形式进行存储,整个存储形状逻辑结构上看,类似于实际生活中倒着的树图 1(B)),所以称这种存储结构为“树型”存储结构

1.2树的基本术语

  • 结点中的一个独立单元。包含一个数据元素若干指向其子树分支,如图1(A)中的A、B、C、D
  • 结点的度结点拥有的子树数成为结点的度。例如,A的度3C的度1F的度0
  • 树的度树的度树内各结点度最大值图1(A)所示的树的度3
  • 叶子0结点称为叶子终端结点结点K、L、F、G、M、I、J都是树的叶子叶子结点孩子
  • 非终端结点度不为0结点称为非终端结点
  • 双亲和孩子结点的子树称为该结点孩子,相应地,该结点称为孩子双亲。例如,B的双亲AB的孩子E和F
  • 兄弟同一个双亲孩子之间互称兄弟。例如,H、I和J互为兄弟
  • 祖先:从该结点所经分支上所有结点。例如,M的祖先A、D和H
  • 子孙:以某结点子树中任一结点都称为该结点的子孙。如B的子孙E、K、L和F
  • 层次结点层次开始定义起第一层根的孩子第二层
  • 堂兄弟双亲同一层结点互为堂兄弟。例如,结点GE、F、H、I、J互为堂兄弟
  • 树的深度树中结点最大层次称为树的深度高度图1(A)所示的树的深度4
  • 有序树无序树:如果将树中结点各子树看成从左至右有次序的(即不能互换),则称该树有序树,否则称为无序树。在有序树最左边子树称为第一个孩子最右边的称为最后一个孩子
  • 森林:是mm≥0)棵互不相交树的集合。把树的根节点删除,它的子树们就构成了森林

1.3线性结构和树结构

线性结构树结构
第一个数据元素无前驱根结点无双亲
最后一个数据元素无后继叶子结点无孩子
其他数据元素一个前驱一个后继一对一其他结点(中间结点)一个双亲多个孩子一对多

1.4二叉树的定义

二叉树nn≥0)个结点所构成的集合,它或为空树n=0);或为非空树,对于非空树

  • 有且仅有一个称之为根的结点
  • 根结点以外其余结点分为两个互不相交的子集T₁和T₂,分别称为T左子树右子树,且T₁T₂本身又都是二叉树

二叉树一样具有递归性质二叉树的区别主要有以下两点

  • 二叉树每个结点至多只有两棵子树(即二叉树中不存在度大于2结点
  • 二叉树子树左右之分,其次序不能任意颠倒

二叉树的递归定义表明二叉树或为,或是由一个根结点加上两棵分别称为左子树右子树的、互不想交二叉树组成。由于这两棵子树也是二叉树,则由二叉树的定义,它们也可以是空树。由此,二叉树可以有5种基本形态,如下图所示:

在这里插入图片描述

树的基本术语是都适用于二叉树的

2.二叉树的性质和存储结构

2.1二叉树的性质

二叉树具有以下几个性质:

在这里插入图片描述
二叉树还有两种特殊的形态满二叉树完全二叉树

  • 二叉树中除了叶子结点每个结点都为2,则此二叉树称为满二叉树

在这里插入图片描述

  • 二叉树中除去最后一层节点满二叉树,且最后一层结点依次从左到右分布,则此二叉树被称为完全二叉树

在这里插入图片描述

  • 满二叉树一定是完全二叉树完全二叉树不一定是满二叉树

2.2二叉树的存储结构

  • 二叉树的存储结构两种,分别为顺序存储链式存储

2.2.1顺序存储

  • 二叉树顺序存储,指的是使用顺序表数组)存储二叉树。需要注意的是,顺序存储只适用于完全二叉树。换句话说,只有完全二叉树才可以使用顺序表存储。因此,如果我们想顺序存储普通二叉树,需要提前将普通二叉树转化为完全二叉树
  • 普通二叉树完全二叉树的方法很简单,只需给二叉树额外添加一些节点,将其"拼凑"成完全二叉树即可。如下图所示,左侧普通二叉树右侧转化后完全(满)二叉树

在这里插入图片描述
解决了二叉树转化问题,接下来我们来学习如何顺序存储完全(满)二叉树完全二叉树顺序存储,仅需从根节点开始,按照层次依次将树中节点存储到数组即可

在这里插入图片描述
例如,存储上图所示的完全二叉树,其存储状态下图所示:
在这里插入图片描述
由此,我们就实现了完全二叉树顺序存储

2.2.2链式存储

其实二叉树不合适数组存储,因为并不是每个二叉树都是完全二叉树普通二叉树使用顺序表存储会存在空间浪费的现象。接下来介绍二叉树链式存储结构
在这里插入图片描述
上图为一颗普通的二叉树,若将其采用链式存储,则只需从树的根节点开始,将各个节点及其左右孩子使用链表存储即可。因此,其对应的链式存储结构如下图所示:
在这里插入图片描述
由上图可知,采用链式存储二叉树时,其节点结构3部分构成:

  • 指向左孩子节点指针Lchild
  • 节点存储的数据data
  • 指向右孩子节点指针Rchild

其实,二叉树链式存储结构远不止上图所示的这一种。例如,在某些实际场景中,可能会做 “查找某节点的父节点” 的操作,这时可以在节点结构中再添加一个指针域,用于各个节点指向其父亲节点,如下图 所示:
在这里插入图片描述

2.3遍历二叉树

  • 二叉树的一些应用中,常常要求在树中查找具有某种特征结点,或者是对树中全部结点逐一处理,这就提出了一个遍历二叉树问题遍历二叉树是指按某一条搜索路径巡访树中每个结点,使得每个结点均被访问一次,而且仅被访问一次遍历二叉树二叉树最基本的操作,也是二叉树其他各种操作基础遍历的实质是对二叉树进行线性化的过程,即遍历的结果是将非线性结构树中结点排成一个线性序列。由于二叉树每个结点都有可能有两棵子树,因而需要寻找一种规律,以便使二叉树上的结点排列在一个线性队列上,从而便于遍历
  • 二叉树是有基本单元组成:根节点、左子树、右子树。因此,若能依次遍历三部分,便是遍历了整个二叉树。假如L、D、R分别表示遍历左子树、访问根节点、遍历右子树,则可有DLR、LDR、LRD、DRL、RDL、RLD6种遍历二叉树的方案。若限定先左后右,则只有前3种情况,分别称之为先(根)序遍历中(根)序遍历后(根)序遍历

基于二叉树递归定义,可得下述遍历二叉树递归算法定义。

先序遍历二叉树的操作定义如下:
  若二叉树,则空操作;否则
  (1)访问根节点
  (2)先序遍历左子树
  (3)先序遍历右子树

中序遍历二叉树操作定义如下:
  若二叉树,则空操作;否则
  (1)中序遍历左子树
  (2)访问根节点
  (3)中序遍历右子树

后序遍历二叉树的操作定义如下:
  若二叉树,则空操作;否则
  (1)后序遍历左子树
  (2)后序遍历右子树
  (3)访问根节点

在这里插入图片描述
例如,上图的二叉树表示的为表达式:a+b*(c-d)-e/f

  • 先序遍历二叉树,可得到二叉树先序序列为:-+a*b-cd/ef
  • 中序遍历二叉树,可得此二叉树中序序列为:a+b*c-d-e/f
  • 后序遍历二叉树,可得此二叉树后序序列为:abcd-*+ef/-

2.4大作业:二叉树的基本操作

构建二叉树(遍历列表按照先序顺序插入值)

测试案例输入列表[‘A’,‘B’,‘C’,’#’,’#’,‘D’,‘E’,’#’,‘G’,’#’,’#’,‘F’,’#’,’#’,’#’],输出的遍历结果见下图

在这里插入图片描述

二叉树的生成,需要用以上输入列表的数值哦;对于非递归遍历,需要用到

2.4.1代码思路(仅供参考,思路不限):

二叉树生成

  • 构建结点类,构建二叉树类
  • 输入一个列表,然后从列表取数,按照先序顺序进行递归插入数值,即先创建根结点,再左子树,再右子树
  • 首先输入一个字符,判断其是否为,不是的即创建根结点该结点数值域该字符,继续递归生成左子树,输入第二个字符,判断其是否为,不是的即生成结点,是的将返回上一层递归,如此判断递归生成二叉树

二叉树遍历

  • 按照先序、中序、后序遍历顺序输出字符即可
  • 非递归的遍历是需要借助栈的
  • 中序遍历非递归算法思想来举例:定义一个空栈,从根结点开始访问,若当前节点非空,则将该节点压栈并访问其左子树循环执行,直至当前节点时,取栈顶元素访问并弹栈,然后访问其右子树,再重复如上操作,直至遍历节点的指针为空并且栈也为空

2.4.2代码实践(递归写法)

class Tree:def __init__(self, item):self.item = itemself.l = Noneself.r = Nonedef llink(self, other):  #左连接子节点self.l = otherdef rlink(self, other): # 右连接子节点self.r = otherdef get_depth(self): # 获取深度(递归)if self.l == None:l_depth = 0else:l_depth = self.l.get_depth()if self.r == None:r_depth = 0else:r_depth = self.r.get_depth()return max(l_depth, r_depth) + 1def get_len(self):  # 获取节点数(递归)if self.l == None:l_len = 0else:l_len = self.l.get_len()if self.r ==None:r_len = 0else:r_len = self.r.get_len()return l_len + r_len + 1def show_first(self):  # 先序遍历(递归)print(self.item, end=" ")if self.l != None:self.l.show_first()if self.r != None:self.r.show_first()def show_mid(self):  # 中序遍历(递归)if self.l != None:self.l.show_mid()print(self.item, end=" ")if self.r != None:self.r.show_mid()def show_last(self):  # 后序遍历(递归)if self.l != None:self.l.show_last()if self.r != None:self.r.show_last()print(self.item, end=" ")def create(x):try:tmp = next(x)if tmp == "#":returnroot = Tree(tmp)root.llink(create(x))root.rlink(create(x))return rootexcept:passtree_list = ['A', 'B', 'C', '#', '#', 'D', 'E', '#', 'G', '#', '#', 'F', '#', '#', '#']
it = iter(tree_list)
root = create(it)# 先序遍历
print(root.show_first())# 中序遍历
print(root.show_mid())# 后序遍历
print(root.show_last())

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MYSQL——多表设计以及数据库中三种关系模型

大致介绍数据库中三种关系模型 一对多(1:N) 定义: 一个实体可以与另一个实体的多个实例相关联,而后者只能与前者的一个实例相关联。 例子: 学生和课程的关系。 学生(1):每个学生…

企业网页设计的安全与数据保护

企业网页设计不仅要考虑美观和功能性,安全与数据保护也是重中之重。在这个信息爆炸的时代,用户的数据隐私和安全问题日益凸显,企业必须采取多种措施来保障用户的信息安全。 首先,**SSL加密**是基础中的基础。通过使用SSL证书&…

观察者模式和订阅模式

观察者模式和订阅模式在概念上是相似的,它们都涉及到一个对象(通常称为“主题”或“发布者”)和多个依赖对象(称为“观察者”或“订阅者”)之间的关系。然而,尽管它们有相似之处,但在某些方面也…

logback动态获取nacos配置

文章目录 前言一、整体思路二、使用bootstrap.yml三、增加环境变量四、pom文件五、logback-spring.xml更改总结 前言 主要是logback动态获取nacos的配置信息,结尾完整代码 项目springcloudnacosplumelog,使用的时候、特别是部署的时候,需要改环境&#…

工具学习_Docker

0. Docker 简介 Docker 是一个开源平台,旨在帮助开发者构建、运行和交付应用程序。它通过容器化技术将应用程序及其所有依赖项打包在一个标准化的单元(即容器)中,使得应用程序在任何环境中都能保持一致的运行效果。Docker 提供了…

基础知识学习上

基础知识学习上 1.关于print1.1 format 方法 2.运算符2.1 除法运算2.2 幂运算 3.条件控制语句3.1 if语句3.2 循环语句 4.复杂数据类型4.1列表4.2字典4.3字符串 5.函数 1.关于print 分隔符 print(1, 2, 3, 4, sep-) print(1, 2, 3, 4, sep。)结尾符 print(1, 2, 3, 4, end?) pr…

无监督跨域目标检测的语义一致性知识转移

Semantic consistency knowledge transfer for unsupervised cross domain object detection 无监督跨域目标检测的语义一致性知识转移 作者: Zichong Chen, Ziying Xia, Xiaochen Li, Junhao Shi, Nyima Tashi, Jian Cheng 所属机构: 电子科技大学信息与通信工程学院&…

AI智能稿件排版系统订单管理系统

在现代制造业和服务行业中,高效的生产流程和精确的订单管理是企业保持竞争优势的核心要素。AI智能稿件排版系统和订单管理系统作为一体化解决方案,以其强大的自动化能力和智能化技术,帮助企业实现排版效率提升、数据格式兼容性增强和生产流程…

Android Google登录接入

官方文献: 1、前期准备: https://developers.google.cn/identity/sign-in/android/legacy-start-integrating?hlzh-cnhttps://developers.google.cn/identity/sign-in/android/legacy-start-integrating?hlzh-cn 2、具体开发: 新版 Googl…

论文浅尝 | MindMap:知识图谱提示激发大型语言模型中的思维图(ACL2024)

笔记整理:和东顺,天津大学硕士,研究方向为软件缺陷分析 论文链接:https://aclanthology.org/2024.acl-long.558/ 发表会议:ACL 2024 1. 动机 虽然大语言模型(LLMs)已经在自然语言理解和生成任务…

Spring Cloud Data Flow快速入门Demo

1.什么是Spring Cloud Data Flow? Spring Cloud Data Flow 是一个用于构建和编排数据处理流水线的云原生框架。它提供了一种简化的方式来定义、部署和管理数据处理任务和流应用程序。以下是一些关键特性和组件: 关键特性 流处理: 支持实时数…

C# .NET环境下调用ONNX格式YOLOV8模型问题总结

我的环境是: Visual Studio: 2019 显卡: 一、遇到问题 1、EntryPointNotFoundException:无法在DLL“onnxruntime”中找到名为“OrtGetApiBase”的入口点。差了下原因,入口点是启动项中的问题。 原因:之前用yolov7时安装的版本在C…

量子感知机

神经网络类似于人类大脑,是模拟生物神经网络进行信息处理的一种数学模型。它能解决分类、回归等问题,是机器学习的重要组成部分。量子神经网络是将量子理论与神经网络相结合而产生的一种新型计算模式。1995年美国路易斯安那州立大学KAK教授首次提出了量子…

AI Large Language Model

AI 的 Large Language model LLM , 大语言模型: 是AI的模型,专门设计用来处理自然语言相关任务。它们通过深度学习和庞大的训练数据集,在理解和生成自然语言文本方面表现出色。常见的 LLM 包括 OpenAI 的 GPT 系列、Google 的 PaLM 和 Meta…

运维团队3D可视化智能机房管理方案

随着信息技术的飞速发展,机房作为信息技术基础设施的核心部分,其管理效率与可视化程度对运维团队的工作质量有着直接影响。本文将介绍一种结合3D可视化技术的机房管理方案,为运维团队提供一种新的视角和工具,以提升机房管理的效率…

CKA认证 | Day2 K8s内部监控与日志

第三章 Kubernetes监控与日志 1、查看集群资源状态 在 Kubernetes 集群中,查看集群资源状态和组件状态是非常重要的操作。以下是一些常用的命令和解释,帮助你更好地管理和监控 Kubernetes 集群。 1.1 查看master组件状态 Kubernetes 的 Master 组件包…

111 - Lecture 10

File I/O and GUI with JavaFX 文件输入/输出与JavaFX图形用户界面 一、Overview 1. File I/O (1) learning Java File I/O mechanism (2) writing into and reading from a file 使用文件I/O进行数据读取和…

分享一下arr的意义(c基础)(必看)(牢记)

arr 即数组名 一般指数组首元素地址 在两种情况下不是 1:sizeof(arr) arr指整个数组简单讲解一下strlen与sizeof(c基础)_strzeof在c语言中什么意思-CSDN博客 2:printf("%p",&…

大数据基于Spring Boot的化妆品推荐系统的设计与实现

摘 要 随着大数据时代的到来,人们对于个性化服务的需求越来越高。化妆品推荐系统作为一个认知智能模型段,在为消费者提供更好的购物体验方面发挥了重要作用。本研究基于大数据技术设计了一个高效准确的化妆品推荐系统。通过对海量数据的分析和处理&…

NUXT3学习日记四(路由中间件、导航守卫)

前言 在 Nuxt 3 中,中间件(Middleware)是用于在页面渲染之前或导航发生之前执行的函数。它们允许你在路由切换时执行逻辑,像是身份验证、重定向、权限控制、数据预加载等任务。中间件可以被全局使用,也可以只在特定页…