数据结构——非线性结构(树与二叉树)
文章目录
- 一. 非线性结构的概述
- 二. 树的基本概念
- 1. 树的定义
- 2. 专业术语
- 3. 树的性质
- 三. 树的分类
- 1. 一般树
- 2. 二叉树(是有序树)
- 2.1 概念
- 2.2 分类
- 1. 一般二叉树
- 2. 满二叉树
- 3. 完全二叉树
- 2.3 二叉树的性质
- 2.3.1 二叉树的常考性质
- 2.3.2 完全二叉树的常考性质
- 3. 森林
- 四. 树的存储
- 1. 来源
- 2. 二叉树的存储
- 2.1 连续存储(必须转化为完全二叉树)
- 2.2 链式存储
- 2.2.1 二叉树链式存储结构描述
- 3. 一般树的存储(用线性来存储非线性结构方法)
- 3.1 双亲表示法(求父节点方便)
- 3.2 孩子表示法(求子节点方便)
- 3.3 双亲孩子表示法(求父节点和子节点都很方便)
- 3.4 孩子兄弟表示法(二叉树表示法)
- 4. 森林的存储
- 4.1 森林转化为二叉树
- 4.2 存储方法
- 4.3 转化方法
- 五. 树的操作
- 1. 二叉树的遍历
- 1.1 先序遍历(先访问根节点)
- 1.2 中序遍历(中间访问根节点)
- 1.3 后序遍历(最后访问根节点)
- 1.4 层次遍历
- 1.5 已知两种遍历序列求原始二叉树
- 2. 森林的遍历
- 2.1 先序遍历森林
- 2.2 中序遍历森林
- 六. 树与二叉树的应用
- 1. 树是数据库中数据组织的一种重要形式
- 2. 操作系统子父进程关系本身就是一棵树
- 3. 面向对象语言中类的继承关系本身就是一棵树
- 4. 线索二叉树
- 4.1 线索二叉树的基本概念
- 4.2 二叉树的基本操作
- 4.2.1 二叉树的线索化构造
- 4.2.2 线索二叉树找前驱/后继
- 7. 哈夫曼树(最优二叉树)
- 7.1 基本概念
- 7.1.1 节点的权、带权路径长度
- 7.1.2 哈夫曼树的定义
- 7.2 哈夫曼树的构造
- 7.3 哈夫曼编码
一. 非线性结构的概述
二. 树的基本概念
1. 树的定义
专业定义:
- 1)有且只有一个称为根的节点
- 2)有若干个互不相交的子树,这些子树本身也是一棵树(递归定义)
通俗定义:
- 1)树是由节点和边组成
- 2)每个节点只有一个父节点但可以有多个子节点
- 3)但有一个节点除外,该节点没有父节点,此节点称为根节点(n个节点的树中有n-1条边)
2. 专业术语
- 节点:一个个圈
- 父节点:和它紧挨着的上面的节点(只有一个)
- 子节点:父节点的下层节点
- 深度:从根节点(第一层)到最底层节点的最大层数
- 高度:从叶子节点开始自底向上逐层累加,数值等于深度
- 叶子节点:没有子节点的节点
- 非终端节点(分支节点):实际就是非叶子节点
- 根节点:既可以是叶子结点,又可以是非叶子节点
- 节点的度:这个节点拥有子节点的个数
- 树的度:树内各节点度的最大值
- 子孙:他下面所有的节点
- 堂兄弟:父亲是兄弟,他们就是堂兄弟
- 有序树和无序树:树中节点每个子树从左到右有次序,不能互换,称此树为有序树,否则称为无序树
- 路径:两节点的路径由这两个节点之间所经过节点序列构成
- 路径长度:路径上经过边的个数
- 树的路径长度:树根到每个节点路径长度之和
3. 树的性质
三. 树的分类
1. 一般树
定义:任意一个节点的子节点的个数都不受限制
2. 二叉树(是有序树)
2.1 概念
定义:任意一个节点的节点个数最多两个,且子节点的位置不可更改(有左右之分)
2.2 分类
1. 一般二叉树
2. 满二叉树
定义:在不增加树的层数的前提下,无法再多添加一个节点的二叉树
3. 完全二叉树
定义:
- 如果只是删除了满二叉树最底层最右边的连续若干节点,这样形成的二叉树
性质:
- 完全二叉树的一个特例是满二叉树
目的:
- 为了解决树以数组方式的存储问题
2.3 二叉树的性质
2.3.1 二叉树的常考性质
2.3.2 完全二叉树的常考性质
3. 森林
定义:n(n≥0)个互不相交的树的集合
四. 树的存储
1. 来源
- 由于内存是一个线性一维的,想要用线性结构存储非线性结构比较困难
- 所以我们学习树这种存储,就是为了学会如何将树这种类型的数据结构存储到计算机上面
树的存储最核心的是:以二叉树存储
二叉树的算法比较成熟:
所以
2. 二叉树的存储
2.1 连续存储(必须转化为完全二叉树)
1)想要将一般的二叉树以数组方式存储的话,必须先将一般二叉树转化为完全二叉树再存储
为什么要添加无效节点(0表示空节点)?
- 因为若只存储有效节点,不添加额外无用的节点,就无法确定以前的树的构造形态(也就是无法还原树的形态)
存储有效节点方式?
- 因为树是非线性结构,而内存是线性结构来存储,所有只有将非线性结构转化为线性结构
- 所有人们造出了三种规定:先序、中序、后序遍历来转化为三种不同的线性结构。但若一个二叉树只存放有效节点,无论以哪一种遍历方式转化的线性结构来存储都无法还原到原来的二叉树形态(tip:这里系统一般只存储一种遍历方式,与后面已知两种遍历方式推出二叉树结构不同)
2)以完全二叉树来存储优缺点
优点:
- 知道了节点的个数就知道这棵树有几层
- 已知任何一个节点,就可知道它的父节点是谁,它的子节点是谁,以及它有没有子节点
缺点:
- 耗费内存
2.2 链式存储
2.2.1 二叉树链式存储结构描述
节点结构包含3个域:数据域 data、左指针域 lchild、右指针域 rchild
二叉树链式存储的优缺点:
缺点:
- 浪费一点空间,即空指针域
- 在含有n个节点的二叉链表中,含有n+1个空链域
优点:
- 求子节点很方便
- 空间利用率高
- 解决了在计算机中存储非连续结构的二叉树(通过用指针域链成一个有层次的树)
3. 一般树的存储(用线性来存储非线性结构方法)
3.1 双亲表示法(求父节点方便)
3.2 孩子表示法(求子节点方便)
3.3 双亲孩子表示法(求父节点和子节点都很方便)
- 操作较为复杂
- 不能使用子节点下标,必须使用子节点指针域
- 子节点可能为多个,也可能没有
3.4 孩子兄弟表示法(二叉树表示法)
把一个普通树转化成二叉树来存储具体转化方法:
- 设法保证任意一个节点的:左指针域指向它的第一个孩子、右指针域指向它的第一个兄弟
只要能满足此条件,就可以把一个普通树转化为二叉树
tip:一个普通树转化成的二叉树,一定没有右子树
4. 森林的存储
4.1 森林转化为二叉树
4.2 存储方法
先把森林转化为二叉树,再去存储二叉树
4.3 转化方法
把B和G当做A的兄弟,再用一般树转化为二叉树方法即可
五. 树的操作
人类造出三种规则:先序、中序、后序这三种遍历,都可以把一个非线性的树转化成一个线性序列
这样方便可以在我们硬件上存储(因为现实中很多问题是非线性的,但硬件的内存条存储是线性的,故想要在内存上存储必须先线性化)
1. 二叉树的遍历
1.1 先序遍历(先访问根节点)
- 先访问根节点
- 再先序访问左子树
- 再先序访问右子树
本质:递归访问
1.2 中序遍历(中间访问根节点)
- 中序遍历左子树
- 再访问根节点
- 再中序遍历右子树
1.3 后序遍历(最后访问根节点)
- 后序遍历左子树
- 后序遍历右子树
- 再访问根节点
三种遍历算法的总结:
- 递归遍历左右子树顺序是固定的,只是访问根的顺序不同。
- 时间复杂度O(n):因为不管采用哪种遍历算法,每个节点都访问一次
- 空间复杂度:为递归工作栈的深度 = 树的深度,所以最坏情况下,二叉树n个节点的深度为n的单分支,那么空间复杂度为O(n)
1.4 层次遍历
按照1,2,3,4的层次顺序,对二叉树中的各个结点进行访问
层次遍历需要借助一个队列
- 先将根节点入队、再出队、再访问出队元素
- 若有左子树,将左子树根节点入队、在出队、再访问出队元素
- 若也有右子树,将右子树根节点入队、在出队、再访问出队元素
- …直到队列为空
1.5 已知两种遍历序列求原始二叉树
若我们已知一课二叉树的先序、中序、后序中的任何一种,都不能把原始二叉树给还原出来。
我们只有通过(先序和中序) 或 (中序和后序)可以还原出原始的二叉树,但是通过先序和后序是无法还原出原始的二叉树的。
1)已知先序和中序求后序
解释:
先看先序,第一个出现A即为根节点
然后看中序,找A的位置,来确定左、右子树
- 那么BDCE为左子树、FHG为右子树,但又不知道哪个是根,不知道左边第一个写啥
- 所以再看先序中BDCE哪个先出现,哪个就是根,可见B先出现为根,再看中序,再来确定B为根的话,那他两边左、右子树又是谁?
- 有因为B只有右边有数,可见B没有左子树,只有右子树DCE,再同理,继续确定B左子树的根
先序找根,中序找左右子树
2)已知中序和后序求先序
解释一下:
先看后序最后出现是根节点A
再看中序可知左、右子树,想确定左、右子树的根节点
- 所以看后序中左、右子树对应部分中哪个最后出现则为根
同理,再确定左、右子树
3)总结:
已知(中序+后序)或(中序+前序)或(中序+层序)可得一颗二叉树
- 其中中序只能确定大体的某根节点左右两侧节点的大致情况,除非左右两侧只有一个节点,否则不好确定左右两侧节点位置
- 通过:后/前/层序来确定每一个具体的根节点的位置
2. 森林的遍历
2.1 先序遍历森林
2.2 中序遍历森林
六. 树与二叉树的应用
1. 树是数据库中数据组织的一种重要形式
2. 操作系统子父进程关系本身就是一棵树
3. 面向对象语言中类的继承关系本身就是一棵树
4. 线索二叉树
4.1 线索二叉树的基本概念
1)线索二叉树的来源
- 传统的二叉树找前驱、后继很不方便,遍历操作必须从根开始
- 传统二叉链表只能体现父子关系,不能得到遍历中的节点的前驱和后继节点
- 且传统的含有n个节点的二叉链表有n+1个空指针
- 因此想利用这些空指针来存放指向前驱或后继的指针
2)引入线索二叉树的目的:
- 加快查找前驱节点和后继节点的速度
3)线索二叉树的节点结构
- 规定:若无左子树,令lchild指向其前驱节点;若无右子树,令rchild指向其后继节点,标志域指示节点的指向。
4)线索二叉树的存储结构
5)线索二叉树的分类
- 中序线索二叉树:按照中序遍历进行线索化
- 先序线索二叉树:按照先序遍历进行线索化
- 后序线索二叉树:按照后序遍历进行线索化
4.2 二叉树的基本操作
4.2.1 二叉树的线索化构造
定义:
- 将原始二叉链表中的空指针改为指向前驱或后继的线索。(由于想知道前驱和后继的信息,必须遍历一遍二叉树)。所以线索化的本质:遍历一次二叉树
一、中序线索二叉树
1)定义:
- 按照二叉树中序遍历序列画线索
2)构造中序线索二叉树
3)中序线索二叉树的存储
二、先序线索二叉树
1)定义:
- 按照先序序列,依次判断每个节点左右链域,若为空则将其改造为线索
2)构造先序线索二叉树
3)先序线索二叉树的存储
三、后序线索二叉树
1)定义:
- 按照后序序列,依次判断每个节点左右链域,若为空则将其改造为线索
2)构造后序线索二叉树
3)后序线索二叉树的存储
4.2.2 线索二叉树找前驱/后继
7. 哈夫曼树(最优二叉树)
7.1 基本概念
7.1.1 节点的权、带权路径长度
7.1.2 哈夫曼树的定义
7.2 哈夫曼树的构造
tip
- 左右孩子节点的顺序是任意的,所有构造出的哈夫曼树并不唯一,但各哈夫曼树的带权路径长度WPL相同且为最优
- 但建议每一层编号按从小到大进行排序
7.3 哈夫曼编码
tip
- 利用哈夫曼树可以设计出总长度最短的二进制前缀编码
- 0/1究竟是表示左子树还是右子树没有明确规定
参考文献
- 郝斌<数据结构>
- 王道考研<数据结构>
数据结构——非线性结构(树与二叉树)相关推荐
- 数据结构 非线性结构 树 介绍及存储方法
所谓树, 其实跟链表有类似的地方, 就是都是由节点和指针构成的数据结构. 在链表中, 每1个节点(尾节点除外)只有1个指针指向下1个节点. 所以链表各个节点可以由一条线链接起来, 就是一种线性结构 ...
- 数据结构——非线性结构 之 二叉树,详细解析
要认识二叉树,首先要先了解树,二叉树是树的一种特殊的结构. 目录 一.树 1.1树的概念和结构 1.2树的相关专业名词 1.3树和非树 二.二叉树 2.1二叉树的概念的结构 三.二叉树的功能实现 3. ...
- 数据结构与算法——树和二叉树***
第五章 :树和二叉树 树和图是两种重要的非线性结构.线性结构中结点具有唯一前驱和唯一后继的关系,而非线性结构中结点之间的关系不再具有这种唯一性.其中,树形结构中结点间的关系是前驱唯一而后继不唯一,即元 ...
- 数据结构——非线性结构(图)
文章目录 一. 非线性结构的概述 二. 图的基本概念 1. 定义 2. 无向图.有向图 2.1 无向图 2.2 有向图 2.3 简单图 2.4 多重图 3. 顶点的度.出度.入度 3.1 对于无向图 ...
- 树形结构—树和二叉树
文章目录 概述 一.树的定义 二.树的基本术语 三.为什么要研究二叉树 四.二叉树和树的区别 五.二叉树的定义 六.二叉树的不同形态 小结 概述 其实,生活中树型结构有很多应用,比如:自然界中的树,人 ...
- Python__数据结构与算法——树、二叉树(实现先、中、后序遍历)
目录 一.树 二.二叉树 树和前面所讲的表.堆栈和队列等这些线性数据结构不同,树不是线性的.在处理较多数据时,使用线性结构较慢,而使用树结构则可以提高处理速度.不过,相对于线性的表.堆栈和队列等线性数 ...
- 数据结构与算法 | 树与二叉树
树的概念 二叉树的概念 树的概念和结构 树是一种非线性的数据结构,它是由n个有限结点组成一个具有层次关系的集合,把它叫做树是因为它看起来像一棵倒挂的树,如图所示 有一个特殊的结点,称为根节点,根节点没 ...
- 数据结构实验二 树和二叉树的实现
广州大学学生实验报告 开课实验室:计算机科学与工程实验(电子楼418A) 2019年5月13日 学院 计算机科学与教育软件学院 年级.专业.班 计算机科学与技术172班 姓名 学号 17061 ...
- 树形结构 —— 树与二叉树
[概述] 树是一种非线性的.递归定义的有序数据结构,能很好地描述有分支和层次特性的数据集合. 二叉树是树的一种形态,是 n 个结点的有限集合,该集合或为空集(空二叉树),或由一个根结点与两棵互不相交的 ...
最新文章
- 黑马程序员的课程不如兄弟连兄弟会好
- 19道Python练习题
- 试用c51语言采样连续5次异常_学会这些自闭症儿童语言训练技巧,孩子开口说话不再困难...
- SpringBoot入门详解源码分析
- 分布式之数据库和缓存双写一致性方案解析!
- 学大数据找IT十八掌
- js传中文参数 java取_js中文转码传输java后台 适用于用url传递中文参数
- 【NeurIPS2020】Google点针图网络,Pointer Graph Networks
- 在Java代码(非JSP及Action,Servlet,Controller)中获得WebRoot的物理路径
- linux从青铜到王者学习好文
- LabVIEW开发结构监控系统
- 希望Online -- 前10级快速功略 + 怪物掉的装备
- android 圆形背景文字,android圆形图片,圆形背景文字的CircleTextImageView开源组件
- 中国古代木制机器发展简史
- matlab图片固定阙值分割
- WiFiAp探究实录--功能实现与源码分析
- LTE学习---PLMN选网(23.122协议R9)
- 腾讯文档自动填写工具(工具)
- 2022-2028年全球与中国光谱比色计行业市场深度调研及投资预测分析
- torchtext使用-- 单标签多分类任务TREC
热门文章
- MP4 ftyp box解析
- Openshift概念
- Kubernetes(K8S)(六)——service(ClusterIP、NodePort、无头服务、LoadBalancer、ExternalName等)
- 转 新入职程序员心得
- java 锁升级_Java并发 锁优化和锁升级
- Frog Jumps
- 关于okhttp(java.lang.NoSuchMethodError: No interface method rangeEquals(JLokio/ByteString;)Z)错误
- 数学建模:种群竞争模型
- MATLAB中的共轭转置与转置
- 赠书:HTML5 Canvas 2d 编程必读的两本经典