树与二叉树理解

  树与二叉树

继学习完了字符串和多维数组的内容后,我们新的一章学习了树和二叉树的内容。这一章个人感觉没有学好第二章链表内容的同学,对递归的思想理解不是很深刻的同学学起来因该会很难受。    

树呢,它是一种非线性的数据结构,它是由n个有限结点组成有层次关系的集合。树具有以下特点,可以根据这些特点来判断一个数据结构是否是树


1.每个结点具有0个或多个子结点
2.每个子结点只有一个父结点
3.没有前驱的结为根结点
4.除了根结点外,每个子结点又可以由m棵不相关的子树组成

 

当然,接下来总结一下树的一些术语的说明

 

1. 结点: 包含数据项和指向其它节点的分支

2. 结点的度: 结点所拥有的子树个数

3. 树的度: 树中各结点度的最大值

4. 叶子结点: 即度为0的结点 又叫终端结点

5. 分支结点: 除叶结点以外的其它结点,又叫非终端结点

6. 结点的层次: 从根结点到某结点所经路径上的分支数称为该结点的层次。根结点的层次为1,其余结点为其父结点的层次+1

7. 树的深度:树中结点的最大层次数


: 树的定义用到了递归的概念,根节点下有树,而这些树的根节点,就是它的下层节点

 

 

二叉树

 

和树一样,二叉树也是递归定义的,其结点有左右子树之分,二叉树有五种基本形态,课本上都有介绍,这里就不一一说明了。树和二叉树的主要有两个差别  第一个是树中结点的最大度数没有限制,而二叉树结点的最大度数为,第二个就是树的结点无左、右之分,而二叉树的结点有左,右之分。

在二叉树的基础上又介绍了满二叉树和完全二叉树

满二叉树除最后一层无任何子节点外,每一层上的所有结点都有两个子结点(最后一层上的无子结点的结点为叶子结点)。也可以这样理解,除叶子结点外的所有结点均有两个子结点。节点数达到最大值。所有叶子结点必须在同一层上

如果对一颗具有n个结点的二叉树按层序编号,如果编号为i的结点与同样深度的满二叉树中编号为i的结点在二叉树中的位置完全相同,这棵树就是完全二叉树。

 

二叉树的各种操作,如求叶子节点个数,树的高度宽度之类的算法,都是基于遍历的思想实现的,而遍历算法的实现又要考虑二叉树的存储结构,二叉树的存储主要有两种存储方式:顺序存储和链式存储。

 

顺序存储(一维数组)

二叉树的顺序存储,就是用一组连续的存储单元存放二叉树中的结点。因此,必须把二叉树的所有结点安排成为一个恰当的序列,结点在这个序列中的相互位置能反映出结点之间的逻辑关系,用编号的方法从树根起,自上层至下层,每层自左至右地给所有结点编号,缺点是有可能对存储空间造成极大的浪费,即一个编号为i的结点如果有左右子的话,则左右儿子的编号分别为2i2i+1

最坏的情况下,一个深度为k且只有k个结点的右单支树需要2k-1个结点存储空间。依据二叉树的性质,完全二叉树和满二叉树采用顺序存储比较合适,树中结点的序号可以唯一地反映出结点之间的逻辑关系,这样既能够最大可能地节省存储空间,又可以利用数组元素的下标值确定结点在二叉树中的位置,以及结点之间的关系。

 

链式存储结构

二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。
通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址。然后就可以利用递归来实现二叉树的定义。

两种存储方式各有各的优点,顺序存储方便查找,节省存储空间(针对完全二叉树而言),但是不方便改动。二叉链表存储改动方便,、但是浪费存储空间,不方便查找遍历,基于树的存储我们就可以按照自己想法写出各种算法的代码。

 

树转换为二叉树:兄弟变右儿子

二叉树转换为树:右儿子变兄弟

森林:m棵互不相交的树的集合,m大于0。

森林转换成二叉树:将森林中每棵树都转换成二叉树、第二棵树作为第一棵树的根结点的右子树,将第三课树作为第二棵树的根节点的右子树,依次类推。

二叉树转换成森林:反复断开二叉树根结点的右孩子的右子树指针,直达不存在根结点有右孩子的二叉树为止

树和森林的遍历:只有先序和后序

结论:树的先序遍历等于它对应二叉树的先序遍历,后序遍历等于它对应的二叉树的中序遍历

森林的先序遍历:对森林中每棵树进行先序遍历

森林的后续遍历:对森林中每棵树进行后续遍历

结论:森林的先序遍历等于它对应二叉树的先序遍历,后序遍历等于它对应的二叉树的中序遍历!

 

如何创建最优二叉树:

  1. 从已知的结点个数中选择两个权值最小的两个结点,构成二叉树中的左右子树。
  2. 由步骤1中的左右子树构造一棵新的二叉树,与未使用过的结点或子树组成森林。
  3. 重复步骤12,知道森林中构成一颗二叉树为止。

 

你可能感兴趣的:(c++)