数据结构笔记4:树

目录

树的基本概念

树的性质

二叉树

满二叉树

完全二叉树

平衡二叉树

二叉树性质

二叉树存储结构

普通树转化为二叉树

选择题

应用题

二叉树遍历

线索链表

题目

树与森林

森林遍历

并查集

题目

树应用

二叉排序(查找)树BST

平衡二叉树AVL

哈夫曼树

题目


树的基本概念

树的分支有向,路径从上到下,两孩子结点之间不存在路径

树的性质

  1. 结点个数=度数(分支/孩子结点)之和加1(加根节点)。(配合结点总数=各度数的结点个数和)

N=1+1*N1+2*N2

=N0+N1+N2

2.度为m的树中第i层最多有m^(i-1)个结点。(每一层都满m)

3.高度为h的m次树至多(m^h-1)/(m-1)个结点。(各层等差数列求和)

4.具有n个结点的m叉树的最小高度为logm( n(m-1) + 1 )  向上取整。

每一层都满m,利用性质3:n=(m^h-1)/(m-1)

把n当作已知可反解h

二叉树

满二叉树

高h的满二叉树,结点个数: (2^h)-1

满二叉树从1开始编号,结点i的左儿子为2i

完全二叉树

分支结点与叶子结点编号分界:i<=⌊n/2⌋为分支结点

平衡二叉树

任意结点左右子树深度差不超过1

不能只看根节点:

二叉树性质

  1. 任意二叉树N0=N2+1

证明:N=N0+N1+N2

N=N1+2*N2+1

2.第k层最多结点2^(k-1)个结点

  1. = 、=CSDN新版编辑器这个编号怎么修改不了,还是错的编号
  2. 满二叉树结点总数(累加)
  3. 结点i所在层次⌊log2 i⌋+1

  1. 高度使用公式 log2 (N+1)

公式3为满2叉树,所以需要向上取整

二叉树存储结构

链式存储

含有n个结点的二叉链表中,有n+1个空链域(null)

总指针域2n,非空链域(孩子结点)n-1个

普通树转化为二叉树

规则:左孩子(长子结点转化为左指针),右兄弟(该结点的平层兄弟转化为右指针)

选择题

已知一棵有2011个结点的树,其叶结点个数为116,该树对应的二叉树中无右孩子的结点个数是:1896

二叉树无右孩子->原树无兄弟

应用题

1. 完全二叉树的高度

公式: log2 (N+1)

N=N0+N1+N2

N-1=N1+2*N2

联立得N0=N2+1,用N0表示N2代入公式

  1. 当N1=1,N=2*N0,h= log2 (2*N0+1)
  2. 当N1=0,N=2*N0-1,h= log2 (2*N0) ⌉=⌈ log2 2+ log2 (N0) ⌉= log2 (N0)+1
  1. 高度为h的满m叉树,从1开始编号
  1. 求i结点的第k个孩子结点

第k个子结点j=(i-1)*m+1+k

其中j=(i-1)*m+1+k推导

https://www.cnblogs.com/sharpstill/archive/2012/12/10/2811189.html

等比数列的公式:

解这一道题的关键是充满想象力,m叉树是自相似的。也就是说:你只需要把每一层乘以m(也就是"放大"m倍)就得到也是一个m叉树,只不过没有根,而且是每层都是原m叉树向下平移了一层。

每一层的下面一层,相当于把每一层放大m倍,也就是平移到下面一层了。

所以,在这道题目中,我要想得到下一层i编号节点所在的那个位置的编号,只需要把m (i- 1) 就得到放大后的m叉树i的那个位置之前的点数总和,再+1,因为刚才没算根。

  1. 求i结点的父节点编号

反解双亲编号⌊(i-2)/m⌋+1

  1. 结点i有右兄弟的条件

当结点为父节点的第m个子结点时,无右兄弟:

对父节点j,第m个子结点为j*m+1

不为第m个子结点时,(i-1)%m!=0

二叉树遍历

遍历的时间复杂度O(n),依次访问每个结点

使用栈,递归算法转非递归算法

P赋值为子结点指针,下一次就可以把p压入栈中了

后序遍历的非递归算法,需要增加变量标识

层次遍历使用队列

线索链表

是二叉链表作为二叉树的存储结构(物理)

最常用的线索二叉树是中序线索:

因为方便找前驱后缀;

先序线索难找前驱;

后序线索前驱后继都难找。

线索二叉树的构造

中序:第一个结点为最左侧,最后一个为最右侧结点

要修改指针域,所以参数都是引用

递归子树

判断指针域为空,有前驱(后继),则添加线索

 

中序一般第一个结点的前驱、最后一个结点的后继线索域为空,将其都指向头结点

而头结点的前驱指向根结点,头结点的后继指向遍历序列最后一个

中序线索二叉树遍历:

题目

1.先序与中序相同的情况

2.二叉树线索化后不能有效求解的问题:

后序遍历的后继(后序从下往上,大多数结点依然没有父结点的指针)

  1. 同一先序序列的不同二叉树个数

NLR

法一:根据总层数讨论

法二:前序入栈,中序出栈

  1. 先序、后序相反二叉树的形态

先序NLR、后序LRN、后序反NRL

每层LR只能取1边(单支)

5.编写获得树高度的算法

非递归,将每层最后一个保存在last,比较队首与last,相同则level++

6.根据遍历序列建立二叉树

主要是在数组中划分子树序列

  1. 判断是否完全二叉树

层次遍历,空结点也入队

  1. 找到二叉树中值为x的结点,释放以它为根的子树

因为需要先找子结点再找根,所以按照后序释放

  1. 判断树相似

会一直遍历到空(空为出口)

  1. 二叉树转化为中缀表达式

树与森林

森林遍历

先序遍历
若森林非空,,
1.访问森林中第一棵树的根结点
2.先序遍历第一棵树的子树森林
3.先序遍历除去第一棵树之后剩余的树构成的子树森林
中序遍历
若森林非空,,
1.中序遍历第一棵树的根结点的子树森林
2.访问第一棵树的根结点
3.中序遍历除去第一棵树之后剩余的树构成的子树森林

森林的中序遍历:用树的后根遍历访问每一颗树

并查集

通常用树的父表示法作为并查集的存储结构(树结点的前驱唯一)

元素下标代表元素名,根结点的下标代表子集名,根结点的父结点<0

并查集的操作:

Initial(s)
将集合S中的每个元素都初始化为只有一个单元素的子集合。
Union(s, Root1, root2)
把集合S中的子集合(互不相交)Root2并入子集合Root1
Find(S, x)
查找集合S中单元素x所在子集合,并返回该子集合的名字

题目

  1. 已知一棵有2011个结点的树,其叶结点个数为116,该树对应的二叉树中无右孩子的结点个数是:1896

法一:特殊构造法

法二:

二叉树无右孩子,原树无右兄弟

每个结点的最右子、根结点

二叉树中无右孩子的结点个数=非叶结点数+1=2011-116+1=1896

树应用

二叉排序(查找)树BST

L<N<R无相同值

中序遍历得递增序列

查找操作

参数p保存双亲引用,时间复杂度O(h)

插入操作

子树为空时创建该结点

构造操作

删除操作

1.Z为叶结点可以直接删除;

2.z只有一子,代替z位置;

3.z两子,中序后继x代替z,删除x

中序序列递增有序

查找效率

查找长度SL:查找时经历结点数量

平均查找长度ASL:SL求和取平均

平衡二叉树AVL

平衡因子(h左-h右)绝对值<=1

已知高度h,计算最小平衡二叉树的结点数Nh

递推计算

N0=0

N1=1(第一层N1为根节点)

Nh=Nh-1+Nh-2+1

Nh代表共h层(非第h层)的平衡二叉树的最少结点数

判断是否平衡

后序遍历:

左子树平衡

右子树平衡

整树平衡

平衡二叉树的插入

先插入,再调整最小不平衡子树

四种调整:LL、RR、LR、RL

LL右单旋转

RR左单旋转

LR(在左孩子的右子树插入)先左后右旋转

RL(在右孩子的左子树插入)先右后左旋转

哈夫曼树

带权路径长度

WPL=叶结点w*l之和

哈夫曼树构造

1)n个结点作为n棵仅含有一个根结点的二叉树,构成森林F;
2)生成一个新结点,并从F中找出根结点权值最小的两棵树作为它的左右子树,且新结点的权值为两棵子树根结点的权值之和;

3)F中删除这两个树,并将新生成的树加入到F;
4)重复2,3步骤,直到F中只有一棵树为止

要注意新建立结点的权值不等于该子树的WPL,不要混淆

哈夫曼树性质

1)每个初始结点都会成为叶节点,双分支结点都为新建立的结点
2)权值越大离根结点越近,权值越小离根结点越远
3)哈夫曼树中没有结点的度为1(只有02
4)n个叶子结点的哈夫曼树的结点总数为2n-1,其中度为2的结点(新建立结点)数为n-1

哈夫曼编码

任两个没有相同前缀(建立新结点,而不使用原结点的原因)

哈夫曼树并不唯一,所以毎个字符对应的哈夫曼编码也不唯一
但带权路径长度相同且最优

题目

  1. 试编写一个算法,判断给定的二又树是否是二叉排序树。

中序遍历时升序-->比较中序前驱值与当前值

  1. 利用二叉树遍历的思想编写一个判断二叉树是否是平衡二叉树的算法

bl\br左右子树是否平衡,hl\hr左右子树高度

  1. (2012年计算机联考真题)设有6个有序表ABCDEF,分别含有1035405060200个数据元素,各表元素升序排列。要求通过5次两两合并,6个表最终合并成1个升序表,并在最坏情况下比较的总次数达到最小
    1)给出完整的合并过程,并求出最坏情况下比较的总次数
    2)根据你的合并过程,描述n(n≥2)个不等长升序表的合并策略,并说明理由。
    合并次数最小-哈夫曼树
  1. 由于最先合并的表中的元素,在后续每次合并中都会再次参与比较,因此求最小合并次数类似于求最小带权路径长度,即哈夫曼树。根据哈夫曼树的构造过程,每次选择表集合中长度最小的两个表进行合并

由于合并两个长度分别为mn有序表,最坏情况下需要比较m+n-1
1次合并:最多比较次数=10+35-1=44
2次合并:最多比较次数=40+45-1=84;
3次合并:最多比较次数=50+60-1=109;
4次合并:最多比较次数=85+110-1=194
5次合并:最多比较次数=195+200-1=394
比较的总次数最多为:44+84+109+194+394=825

最好情况为m最大<n最小

最坏的情况是交叉的情况:

1  3  5

2  4  6

上链指p,下链q,每次较小节点作为合并节点,同时指针后移。某链指空后不再比较。

第一步:12比,1小作为新节点,p移至3。第二步,32比,2小作为新节点,q移至4…

2)利用哈夫曼树构造,依次选择最短的两个表进行合并,可以获得最坏情况下最佳的合并效率

猜你喜欢

转载自blog.csdn.net/lagoon_lala/article/details/109564059