一、二叉树
1、定义
二叉树是n个结点的有限集合,且该集合为空集合或者由一个根结点和两棵互不相交的左子树和右子树组成。二叉树的每个结果最多只能有两个孩子结点。如图:
2、特点
1、每个结点最多只能有两棵子树,故二叉树中不存在度大于2的结点
2、左右子树是有顺序的,不能随意颠倒。即使某结点只有一颗子树,也要确定是左子树还是右子树
3、性质
1、在二叉树的第i层上最多只有2^(i-1)个结点。
2、如果二叉树的深度为k,则该二叉树最多有2^k -1个结点
3、度数为0的结点数比度数为2的结点数多 1 个
4、完全二叉树中,具有n个节点的完全二叉树的深度为(log2 n) +1, 其中(log2 n)向下取整
5、若对含n个结点的完全二叉树,从上到下,从左到右进行1-n的编号,则完全二叉树中任意编号为i的结点有如下属性:
1)i=1时,该结点为根结点;否则,编号为i/2 的结点为其双亲结点
2)若2i > n,则该结点无左孩子结点;否则,2i为其左孩子结点
3)若2i+1>n,则该结点无右孩子结点;否则2i+1为其右孩子结点
4、满二叉树
在一颗二叉树中,如果所有的分支结点都有左子树和右子树,并且所有的叶子结点都在同一层,则称为满二叉树。
满二叉树特点:
1、叶子只能出现在最下层
2、非叶子结点的度为2
3、同样深度的二叉树中,满二叉树的结点最多,叶子数最多。
5、完全二叉树
对一颗具有n个结点的二叉树按层编号,如果编号为 i (1<=i<=n)的结点与同样深度的满二叉树中编号为i的结点在二叉树中的位置完全相同,则称为完全二叉树。
完全二叉树特点:
1)叶子结点只能出现在最下层和次下层
2)最下层的叶子结点集中在树的左部
3)次下层如果存在叶子结点,一定是在树的右部
4)如果结点度为1,则该结点只有左孩子结点,没有右孩子结点
5)同样结点数目的二叉树,完全二叉树的深度最小。
二、二叉树存储结构
1、顺序存储
使用一维数组存储二叉树的结点,并且结点的存储位置,就是数组的下标索引
完全二叉树存储前:
存储后:
不完全二叉树存储前(灰色结点为实际结点,白色结点为不存在结点):
存储后(其中^表示不存在结点):
可以看出,对于深度大,结点少的二叉树,顺序存储方式是很消耗内存的
2、二叉链表
由定义可知,二叉树中每个结点最多只有两个孩子结点,可以将结点数据结构定义为一个数据+两个指针域的链表结构。
而二叉树可以表示为:
此种方式存储就会避免顺序存储的内存浪费,还可以动态的加减结点。
三、二叉树的遍历
1、定义:
从二叉树的根结点出发,按照某种次序依次访问二叉树的所有结点,每个结点仅被访问一次。
二叉树的访问次序有四种:前序遍历,中序遍历,后序遍历,层序遍历
1)前序遍历
按照先中间再向左后向右的方向访问,到达结点就输出结点数据。
遍历顺序:
1、从根结点出发,输出根结点A
2、向左访问,下一个是B,输出结点B
3、继续向左访问,遇到结点D,输出结点D
4、继续向左访问,遇到结点H,输出结点H
5、结点H无孩子结点,访问上一级结点D的右孩子结点I,输出结点I
6、结点I无孩子结点,结点D的左右孩子结点已输出,访问上一级结点B的右孩子结点E,输出结点E
7、访问结点E的左孩子结点J,输出结点J
8、结点E无右孩子结点,结点B的左右孩子结点已输出,访问上一级结点A的右孩子结点C,输出结点C
9、访问结点C的左孩子结点F,输出结点F
10、访问结点C的右孩子结点G,输出结点G
输出结果:
ABDHIEJCFG
2)中序遍历
从二叉树的最左侧结点开始,按照先向左再中间再向右的顺序输出结点信息
遍历顺序如下:
1、从根结点A开始,访问左孩子结点B,再访问结点B的左孩子结点D,再访问结点D的左孩子结点H,H无左孩子结点,故输出结点H
2、结点H无孩子结点,返回结点D,输出结点D
3、结点D有右孩子结点I,输出结点I
4、结点I无孩子结点,返回结点D,结点D已输出,返回结点B,输出结点B
5、结点B有右孩子结点E,结点E有左孩子结点J,输出结点J
6、返回结点E,结点E无右孩子结点,输出结点E
7、返回结点B,结点B已输出,返回结点A,输出结点A
8、结点A有右孩子结点C,结点C有左孩子结点F,输出结点F
9、返回结点C,输出结点C
10、结点C有右孩子结点G,输出结点G
输出结果:
HDIBJEAFCG
3)后序遍历
从最左结点开始,按先向左再向右再中间的顺序遍历
遍历顺序如下:
1、从根结点A开始,访问结点A的左孩子结点B,访问结点B的左孩子结点D,访问结点D的左孩子结点H,结点H无孩子结点,输出结点H
2、结点H的双亲结点D有右孩子结点I,输出结点I
3、输出结点D
4、结点D的双亲结点B有右孩子结点E,结点E有左孩子结点J,输出结点J
5、结点J的双亲结点E无右孩子结点,输出结点E
6、结点B的左右孩子都已输出,输出结点B
7、结点B的双亲结点A有右孩子结点C,结点C有左孩子结点F,输出结点F
8、结点F的双亲结点C有右孩子结点G,输出结点G
9、结点G的双亲结点C的左右孩子结点都已输出,输出结点C
10、结点C的双亲结点A左右结点都已输出,输出结点A
输出结果:
HIDJEBFGCA
4)层序遍历
按照树的层次从上到下,从左到右依次遍历
遍历顺序如下:
1、第一层根结点A,输出结点A
2、第二层左起,第一个结点B,输出结点B
3、向右访问,下一个结点为C,输出结点C
4、第三层左起,第一个结点D,输出结点D
5、向右访问,下一个结点为E,输出结点E
6、向右访问,下一个结点为F,输出结点F
7、向右访问,下一个结点为G,输出结点G
8、第四层左起,第一个结点H,输出结点H
9、向右访问,下一个结点为I,输出结点I
10、向右访问,下一个结点为J,输出结点J
输出结果:
ABCDEFGHIJ
总结:
二叉树的遍历方式可以理解为:依据双亲结点在遍历时的处理顺序来区分。前序遍历是先输出双亲结点,再输出左右孩子结点;中序遍历是很多输出左孩子结点,再输出双亲结点,再输出右孩子结点;后序遍历是先输出左右孩子结点,再输出双亲结点。遍历方式及期遍历顺序要牢记,可能会通过前序+中序确认二叉树,或后序+中序来确认二叉树。