概念
1、结点的度:结点拥有的子树个数
2、树的度:树内各结点度的最大值
3、叶结点(终端结点):度为0的结点
4、分支结点:度大于0的结点
5、满二叉树:所有的分支结点都存在左右孩子,左右的叶子结点都在同一层的二叉树
6、完全二叉树:对一棵具有n个结点的二叉树按层编号,如果编号为i(1<=i<=n)的结点与同样深度的满二叉树中编号为i的结点中位置完全相同,那此树就是一棵满二叉树(结点只能从左到右,从上往下生长)
7、平衡二叉树:如果某二叉树中任意结点的左右子树的深度相差不超过1 ,那么它就是一棵平衡二叉树
性质
1、在二叉树的第i层最多有2^(i-1)个结点
2、深度为k的二叉树最多有2^k-1个结点
3、对任何一颗二叉树,若有n0个叶结点,度为2的结点数位n2,则n0 = n2 + 1
(树枝数 = n0 + n1 + n2 -1 = n1 + 2*n2)
4、具有n个结点的完全二叉树的深度为[log2n] + 1(2为底,n的对数)
5、对一棵有n个结点的完全二叉树按层编号(从0开始):
A.若 i = 0,则结点 i 为二叉树的根;若 i > 0, 则其双亲为[(i-1) / 2]
B.若 2 * i +1 > n,则结点 i 无左孩子,否则其左孩子是结点 2 * i + 1
C.若 2 * i +2 > n,则结点 i 无右孩子,否则其右孩子是结点 2 * i + 2
遍历二叉树
先序遍历:根左右
先序代码:
中序遍历:左根右
中序代码:
后序遍历:左右根
后序代码:
层次遍历:从上到下,从左到右
1、把根节点A放入队列,此时队列为:A,队列头指针指向A,也就是队列第一个元素
2、把当前队列头指针所指元素的左右儿子放入队列,即将B C放入队列,此时队列为A B C ,队列头指针向后移一格,此时指向B
3、不断重复2步骤。此时把B的左右儿子取出来放入队尾,队列变为A B C D,
队列头指针后移,指向C。把C的左右儿子取出来放入队尾,队列变为A B C D E F
队列头指针后移,指向D。把D的左右儿子取出来放入队尾,队列变为A B C D E F G H
队列头指针后移,指向E。把E的左右儿子取出来放入队尾,队列变为A B C D E F G H I
4、结束条件,队列头指针和为指针重合时,输出最后一个元素,算法结束!也就是说,把这个队列从头到尾输出一遍,就是按层遍历,这个队列是动态的,只要有子节点,子节点就会不停的加入队尾,但总有子节点没有的时候,所以,队列尾指针肯定有不再移动的时候,而头指针一直在一步一步向下移,总会有首尾指针重合的时候,即标志着算法结束。
层次遍历代码:
注:已知中序遍历和先序遍历结果,或已知中序遍历和后序遍历结果可以还原二叉树
二叉树深度
最简单的方式就是使用递归的方式来遍历二叉树,在递归的处理函数中逐渐增加二叉树的深度
图解(深度为3):
注:‘#’ 表示此结点为空,向调用处返回0,实际的二叉树如下
判断平衡二叉树
递归地检查二叉树中所有结点的左右子树的深度之差,若都相差不超过1 ,那么它就是一棵平衡二叉树
构造二叉搜索树的insert操作
将有序数组转为二叉搜索树
面向过程完整代码:
运行结果:
注:创建结果如上图(二叉树深度部分的图)
面向对象版完整代码
线索二叉树
将普通二叉树线索化成中序线索二叉树:
线索二叉树的数据结构:
中序线索二叉树的存储结构:
将普通二叉树线索化成先序线索二叉树:
先序线索二叉树的存储结构:
将普通二叉树线索化成后序线索二叉树:
后序线索二叉树的存储结构:
用两个指针,在中序遍历的同时,将二叉树中序线索化:
中序线索化实现代码:
先序线索化实现代码:
后序线索化实现代码:
注: 只有构造先序线索二叉树时,才需要判断左指针是否是真实的结点。因为先序遍历的顺序是【根,左,右】,访问根结点后可能会线索化左指针。改变左指针后,马上再接着访问当前根结点的左孩子,就会访问到当前根结点的父结点,然后又访问回来…,这样死循环下去。
别的顺序线索化二叉树,不需要判断左指针是否是真实的结点。中序线索化时,先访问左孩子,由于左孩子线索化后,会接着访问根结点,不会再往下层访问,所以线索化对中序遍历没有影响。后序线索化同样的分析。
中序线索化二叉树完整代码:
树的孩子兄弟表示法:
森林与二叉树相互转换:
先将每棵树按照孩子兄弟表示法转换为二叉树,然后把C、D当作B的兄弟结点,挂到B的后子树上,就像这样:
将二叉树按照孩子兄弟表示法还原为森林:
树的先根遍历
先访问根,在从左往后访问子树
树的后根遍历
先从左往后访问子树,最后访问根
因为树中,不管是左孩子还是右孩子对应到孩子兄弟表示法的二叉树中,都是左孩子。所以树中的【左、右、根】对应成了二叉树中的【左、根】,换到下一颗树遍历时,二叉树就变成了右孩子,故 树的后序遍历 = 对应二叉树的中序遍历
树的层次遍历
森林的遍历
- 森林的先序遍历 = 从左到右对每棵树先序遍历 = 对应二叉树的先序遍历
- 森林的中序遍历 = 从左到右对每棵树后序遍历 = 对应二叉树的中序遍历