树与二叉树

5.1-1 树的定义和基本术语

树的基本概念

树与二叉树_第1张图片
树与二叉树_第2张图片

结点之间的关系描述

两个结点之间的路径只能是 从上往下
树与二叉树_第3张图片
树与二叉树_第4张图片

有序树、无序树、森林

树与二叉树_第5张图片
把森林通过结点连起来就是一棵树
树与二叉树_第6张图片

5.1-2 树的性质

考点1

树与二叉树_第7张图片

考点2

树与二叉树_第8张图片

考点3

树与二叉树_第9张图片

考点4

树与二叉树_第10张图片

考点5

树与二叉树_第11张图片

考点6

树与二叉树_第12张图片

5.2-1 二叉树的定义和基本术语

二叉树的基本概念

树与二叉树_第13张图片

二叉树的五种状态

树与二叉树_第14张图片

几种特殊的二叉树(满二叉树、完全二叉树、二叉排序树、平衡二叉树)

树与二叉树_第15张图片
树与二叉树_第16张图片
树与二叉树_第17张图片
树与二叉树_第18张图片

5.2-2 二叉树的性质

二叉树常考性质

树与二叉树_第19张图片
树与二叉树_第20张图片
树与二叉树_第21张图片

完全二叉树常考性质

树与二叉树_第22张图片
树与二叉树_第23张图片
树与二叉树_第24张图片

总结

树与二叉树_第25张图片

5.2-3 二叉树的存储结构

完全二叉树的顺序存储

树与二叉树_第26张图片
树与二叉树_第27张图片

一般二叉树的顺序存储

树与二叉树_第28张图片
树与二叉树_第29张图片

二叉树的链式存储

线索二叉树之后讲解
树与二叉树_第30张图片
root->data直接赋值了{1},是因为 data是结构体 ElemType类型的,给ElemType类型的赋值{1},相当于给结构体类型的ElemType整体赋值。
树与二叉树_第31张图片
树与二叉树_第32张图片

5.3-1 二叉树的先中后序遍历

先中后序遍历

树与二叉树_第33张图片
树与二叉树_第34张图片
树与二叉树_第35张图片

遍历算数表达式树

树与二叉树_第36张图片

求遍历序列

递归遍历

树与二叉树_第37张图片
树与二叉树_第38张图片
树与二叉树_第39张图片
树与二叉树_第40张图片

空间复杂度分析

树与二叉树_第41张图片
以下占用了函数调用栈的空间,随着深度h的变化,函数调用栈被占用的空间越多。
树与二叉树_第42张图片

非递归遍历

树与二叉树_第43张图片
树与二叉树_第44张图片
树与二叉树_第45张图片

求树的深度

树与二叉树_第46张图片

总结

树与二叉树_第47张图片

5.3-2 二叉树的层次遍历

树与二叉树_第48张图片
树与二叉树_第49张图片

5.3-3 由遍历序列构造二叉树

给出单一中序、前序、后序、层序遍历序列 并不能直接还原唯一的二叉树形态。

树与二叉树_第50张图片
树与二叉树_第51张图片
树与二叉树_第52张图片树与二叉树_第53张图片
由上面中序、前序、后序、层序可知给出 遍历序列 并不能直接还原唯一的二叉树形态。
树与二叉树_第54张图片

前序+中序遍历序列

对前+中 、后+中、层+中都适用:找到树的根节点,并根据中序序列划分左右子树,再找到左右子树根节点。
树与二叉树_第55张图片

例1(过程解析)

树与二叉树_第56张图片
树与二叉树_第57张图片

例2(练习自己做)

树与二叉树_第58张图片

后序+中序遍历序列

树与二叉树_第59张图片

例3(自行练习)

树与二叉树_第60张图片

层序+中序遍历序列

树与二叉树_第61张图片

例4(自行练习)

树与二叉树_第62张图片
树与二叉树_第63张图片
树与二叉树_第64张图片

若前序、后序、层序两两组合?

树与二叉树_第65张图片

5.3-4 线索二叉树的概念

将二叉树 线索化 后,查找结点的前驱、后继就更方便、容易了。

中序线索二叉树

树与二叉树_第66张图片
树与二叉树_第67张图片
树与二叉树_第68张图片

先序线索二叉树

树与二叉树_第69张图片
树与二叉树_第70张图片

后序线索二叉树

树与二叉树_第71张图片
树与二叉树_第72张图片

三种线索二叉树的对比

术语不同

如:中序前驱就是,如果按照中序进行遍历,他的前驱是哪个。
树与二叉树_第73张图片

总结

树与二叉树_第74张图片

5.3-5 二叉树的线索化

中序线索化

中序线索化代码引入

树与二叉树_第75张图片
如图位置后,q指向C,q->lchild != null,不执行下面红框1 的程序,
树与二叉树_第76张图片
pre指向F,pre!=null && pre->rchild=null,所以建立F右边那条紫色的连接。执行红框2的程序。
之后执行红框3 pre=q。
树与二叉树_第77张图片

进行中序线索化的全部代码

树与二叉树_第78张图片

中序线索化的二叉树应是什么样的

树与二叉树_第79张图片

先序线索化(原理类似)

先序线索化代码引入

如图,q指向D,q->lchild=null,q->lchild=pre,q->ltag=1后,本来q的左孩子是空,但是当执行PreThread(T->lchild)时,T->lchild由于刚才线索化了,此时等于之前的 pre指向的B,T->lchild等于B 不等于null,所以又回去执行visit(B)了,这是不好的
树与二叉树_第80张图片
为解决上面问题,在下图中添加箭头指的一句代码 if(T->ltag==0)来判断他有无 真正的左子树,而不是线索。
树与二叉树_第81张图片

进行先序线索化的全部代码

树与二叉树_第82张图片

后序线索化

后序线索化中不会出现先序线索化中转圈的问题。因为是后序先访问左子树,右子树,最后访问根,所以当我们访问一个结点q的时候,这个结点他左孩子那条路已经处理完了,右孩子那条路也处理完了,所以我们访问完这个结点后,不会回头去重新访问左孩子所指向的那棵子树和右孩子所指向的那棵子树了,所以也就不会出现转圈的问题了。

进行后序线索化的全部代码

树与二叉树_第83张图片

5.3-6 在线索二叉树中找前驱后继

中序线索二叉树

中序线索二叉树找中序后继

树与二叉树_第84张图片
树与二叉树_第85张图片
树与二叉树_第86张图片
树与二叉树_第87张图片

中序线索二叉树找中序前驱

根节点p的前驱 应该是左子树中按照中序遍历最后一个结点。即左子树中最右下的结点
树与二叉树_第88张图片
树与二叉树_第89张图片
树与二叉树_第90张图片

先序线索二叉树

先序线索二叉树找后继

树与二叉树_第91张图片

先序线索二叉树找前驱

树与二叉树_第92张图片
下面改为在三叉列表的情况下,多一个指向父结点的指针。
树与二叉树_第93张图片
最右边图示的解释:
根左右,
左子树的最右下边,
如果最右下那个结点有左子树,那么在取该左子树,
如果该左子树有右子树,那么该取最右下边右子树,
总之就是沿着最右边往下走,遇到左边沿着最左边往下走,遇到右边沿着最右边往下走。。。。。。
树与二叉树_第94张图片

后序线索二叉树

后序线索二叉树找前驱

树与二叉树_第95张图片

后序线索二叉树找后继

树与二叉树_第96张图片
下面改为在三叉列表的情况下,多一个指向父结点的指针。
树与二叉树_第97张图片
树与二叉树_第98张图片

5.4-1 树的存储结构(一般的树,不止二叉树)

树与二叉树_第99张图片

双亲表示法

树与二叉树_第100张图片

树与二叉树_第101张图片

树与二叉树_第102张图片
在这里插入图片描述
树与二叉树_第103张图片

孩子表示法

找孩子很方便,找双亲不方便
树与二叉树_第104张图片

孩子兄弟表示法

用孩子兄弟表示法存储的树 在物理上 呈现出“二叉树”的样子。
树与二叉树_第105张图片

森林和二叉树的转换

森林转换为二叉树

树与二叉树_第106张图片

二叉树转换为森林

树与二叉树_第107张图片

5.4-2 树和森林的遍历

树的遍历

树的先根遍历

树与二叉树_第108张图片

树的后根遍历

树与二叉树_第109张图片

树的层次遍历

树与二叉树_第110张图片

森林的遍历

森林的先序遍历

第一种方法

树与二叉树_第111张图片

第二种方法

通过孩子兄弟表示法 转化为二叉树(左孩子右兄弟)
树与二叉树_第112张图片

森林的中序遍历

第一种方法

树与二叉树_第113张图片

第二种方法

通过孩子兄弟表示法 转化为二叉树(左孩子右兄弟)
树与二叉树_第114张图片

总结

森林转化为树后,森林的中序遍历转化为树的后根遍历;
森林转化为二叉树后,森林的中序遍历转化为二叉树的中序遍历。
树与二叉树_第115张图片

5.5-1 哈夫曼树

哈夫曼树

树与二叉树_第116张图片
树与二叉树_第117张图片
树与二叉树_第118张图片
树与二叉树_第119张图片

哈夫曼编码

利用 可变长度编码 可以压缩数据,用更少的比特表示同样多的数据
树与二叉树_第120张图片
如果A不用10来编码,用1来编码,那么A就不是叶子节点了,会造成解码的误解。如下图右边所示,
比如111不知道是3个A还是1个B了。
树与二叉树_第121张图片
树与二叉树_第122张图片

5.5-2 并查集

并查集的逻辑结构(本质是一种表示集合的逻辑关系)

并查集本质上是表示一种集合的逻辑关系,而这个集合要实现的基本操作是
树与二叉树_第123张图片
树与二叉树_第124张图片
树与二叉树_第125张图片

树与二叉树_第126张图片

树与二叉树_第127张图片
双亲表示法更有效:
就是一路向上找到根节点,可以通过比较根节点是否相同来判断是否是同一个集合。
就是将其中一棵树的根节点指向另一棵树的根节点。
树与二叉树_第128张图片

并查集的存储结构(类似双亲表示法,S[]数组中也是存储的其父节点数组下标)

树与二叉树_第129张图片

并查集的基本操作(并、查)

树与二叉树_第130张图片

并查集代码的初始化

树与二叉树_第131张图片

并查集的 查和并 的代码

树与二叉树_第132张图片

并查集的查的举例演示

树与二叉树_第133张图片

并查集的并的举例演示

树与二叉树_第134张图片

代码的时间复杂度分析

树与二叉树_第135张图片

降低时间复杂度的优化思路

上图说明要想时间复杂度低,树就不能太高太长,
优化思路:在每次Union操作构建树的时候,尽可能让树不长高高
树与二叉树_第136张图片

优化过程

三棵树

树与二叉树_第137张图片

前两棵树合并

树与二叉树_第138张图片

三棵树全部合并

树与二叉树_第139张图片

优化后的时间复杂度

树与二叉树_第140张图片

5.5-3 并查集的进一步优化(Find操作的优化(压缩路径))

树与二叉树_第141张图片
树与二叉树_第142张图片
树与二叉树_第143张图片

并查集的优化总结

树与二叉树_第144张图片

你可能感兴趣的:(数据结构,数据结构)