二叉树的相关定义

二叉树定义

二叉树时n ( n≥0 )个结点的有限集合,该集合或者为空集(称为空二叉树),或者右一个根结点和两棵互不相交的、分别称为根结点的左子树和右子树的二叉树组成。

二叉树的特点

  • 每个结点最多有两棵子树,所以二叉树中不存在度大于2的结点。注意不是只有两棵子树,而是最多,没有子树或者只有一棵子树都是可以的;
  • 左子树和右子树是有顺序的,次序不能任意颠倒;
  • 即使树中某节点只有一棵子树,也要区分它是左子树还是右子树。

二叉树的基本形态

  • 空二叉树;
  • 只有一个根结点;
  • 根结点只有左子树;
  • 根结点只有右子树;
  • 根结点既有左子树又有右子树。

特殊二叉树

真二叉树(Full Binary Tree)

所有非叶子节点的度都为2.叶子不一定在同一层。

斜树

所有的结点都只有左子树的二叉树叫左斜树;所有结点都只有右子树的二叉树叫右斜树,两者统称为斜树。

满二叉树(Perfect Binary Tree)

在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子都在同一层上,这样的二叉树就称为满二叉树。

满二叉树的特点

  • 叶子只能出现在最下一层,出现在其他层都不可能达到平衡;
  • 非叶子结点的度一定是2;
  • 在同样深度的二叉树中,满二叉树的结点个数最多,叶子数最多。

完全二叉树(Complete Binary Tree)

对一棵具有n个结点的二叉树按层序编号,如果编号为i (1 ≤ i ≤ n)的结点与同样深度的满二叉树中编号为i的结点在二叉树中位置完全相同,则这棵二叉树就被称为完全二叉树。
所以满二叉树一定是一棵完全二叉树,完全二叉树不一定是满二叉树。
其次,完全二叉树的所有结点与同样深度的满二叉树,它们按层序编号相同的结点,是一一对应的。例如下图中树1,结点5没有左子树却有右子树,那么按层序编号的第10个编号就空挡了,结点5的右子树应该编号11;同样树2的结点3,没有左右子树,那么编号6和7空挡,结点4的左右子树应该编号为8和9;对于树3,因为结点5没有子树,造成第10和第11位置空挡。只有树4,尽管它不是满二叉树,但是编号是连续的,所以它是完全二叉树。
从这些例子中,我们可以总结一个判断某二叉树是否是完全二叉树的办法:
根据树的示意图,给每个结点按照满二叉树的结构逐层顺序编号,如果编号出现空挡,就说明不是完全二叉树,否则就是。
非完全二叉树:在这里插入图片描述
完全二叉树:
在这里插入图片描述

完全二叉树的特点

  • 叶子结点只能出现在最下两层;
  • 最下层的叶子一定集中在左部连续位置;
  • 倒数二层,若有叶子结点,一定都在右部连续位置;
  • 如果结点度为1,则该结点只有左孩子,即不存在只有右结点的情况;
  • 同样结点数的二叉树,完全二叉树的深度最小。

二叉树的性质

性质1:在二叉树的第i层上至多有2i-1个结点(i≥1)

数学归纳法

性质2:深度为k的二叉树至多有2k-1(k≥1)个结点

数学归纳法

性质3:对任何一棵二叉树T,如果其终端结点数为n0,度为2的结点数为n2,则n0=n2+1

终端结点数其实就是叶子结点数,而一棵二叉树,除叶子结点外,剩下的就是度为1或者2的结点数了,我们设n1为度是1的结点数,则树T的结点总数n=n0+n1+n2
我们换个角度,再数一数树T的连接线数,由于根结点只有分支出去,没有分支进入,所以分支线总数为结点总数减1,所以分支线总数 = n - 1 = n1 + 2 * n2,结合等式n=n0+n1+n2,得到n0 = n2 + 1.

性质4:具有n个结点的完全二叉树的深度为[log2n]+1([x]表示不大于x的最大整数)

由满二叉树的定义我们可知,深度为k的满二叉树的结点数n一定是2k-1,因为这是最多的结点个数,那么对于n=2k-1倒推得到满二叉树的度数为k=log2(n+1)。对于完全二叉树,它的结点数一定少于等于同样度数的满二叉树的结点数2k-1,但一定多余2k-1-1,即满足2k-1-1 < n ≤ 2k-1,由于n是整数,所以同样意味着2k-1≤ n < 2k,不等式两边取对数,得到k-1 ≤ log2n < k,而k也是整数,因此k=[log2n]+1。

性质5 如果对一棵有n个结点的完全二叉树(深度为[log2]+1)的结点按层序编号,对任一结点i(1≤i≤n)有:

  • 如果i=1,则结点i是二叉树的根,无双亲;如果i>1,则其双亲是结点[ i / 2 ];
  • 如果2 * i > n,则结点i无左孩子(结点i为叶子结点);否则其左孩子是结点2 * i
  • 如果2 * i + 1 > n,则结点i无右孩子;否则其右孩子是结点2 * i + 1

线索二叉树

二叉树的空结点如果存放指向结点在某种遍历次序下的前驱和后继节点的地址,将大大利用那些空地址。这种指向前驱和后继的指针称为线索,加上线索的二叉链表称为线索链表,相应的二叉树就称为线索二叉树。对二叉树以某种次序遍历使其变为线索二叉树的过程称为线索化
线索化的实质是将二叉链表中的空指针改为指向前驱或后继的线索。由于前驱和后继的信息只有在遍历该二叉树时才能得到,所以==线索化的过程就是在遍历的过程中修改空指针的过程。==在实际问题中,如果所用的二叉树需经常遍历或者查找结点时需要某种遍历序列中的前驱和后继,那么采用线索二叉树的存储结构就是非常不错的选择。

树、森林和二叉树的转换

树转换为二叉树

将树转换为二叉树的步骤如下:
1、加线,在所有兄弟结点之间加一条连线;
2、去线,对树中每个结点,只保留它与第一个孩子结点的连线,删除它与其他孩子结点之间的连线(兄弟之间的连线要留着);
3、层次调整,以树的根结点为轴心,将整棵树顺时针旋转一定的角度,使之结构层次分明。注意第一个孩子是二叉树结点的左孩子,兄弟转换过来的孩子是结点的右孩子。
在这里插入图片描述

森林转换为二叉树

森林是由若干棵树组成的,所以完全可以理解为,森林中的每一棵树都是兄弟,可以按照兄弟的处理办法来操作,步骤如下:
1、把每棵树转换为二叉树;
2、第一棵二叉树不动,从第二棵二叉树开始,依次把后一棵二叉树的根结点作为前一棵二叉树的根结点的右孩子,用线连接起来。当所有的二叉树连接起来后就得到了由森林转换来的二叉树。
在这里插入图片描述

二叉树转换为树

二叉树转换为树是树转换为二叉树的逆过程,也就是反过来做而已。步骤如下:
1、加线,若某结点的左孩子结点存在,则将这个左孩子的右孩子结点、右孩子的右孩子结点、右孩子的右孩子的右孩子结点……,反正就是左孩子的n个右孩子结点都作为此结点的孩子,将该结点与这些右孩子结点用线连接起来;
2、去线,删除原二叉树中所有结点与其右孩子结点的连线;
3、层次调整,使之结构层次分明。
在这里插入图片描述

二叉树转换为森林

判断一棵二叉树能够转换成一棵树还是森林,标准很简单,那就是只要看这棵二叉树的根结点有没有右孩子,有就是森林,没有就是一棵树。那么如果是转换成森林,步骤如下:
1、从根结点开始,若右孩子存在,则把与右孩子结点的连线删除,再查看分离后的二叉树,若右孩子存在,则连线删除……,直到所有右孩子连线都删除为止,得到分离的二叉树;
2、再将每棵分离后的二叉树转换为树即可;
在这里插入图片描述

树与森林的遍历

树的遍历分为两种方式。
1、一种是先根遍历树,即先访问树的根结点,然后依次先根遍历根的每棵子树。
2、另一种是后根遍历,即先依次后根遍历每棵子树,然后再访问根结点。

森林的遍历也分为两种方式。
1、前序遍历:先访问森林中第一棵树的根结点,然后再依次先根遍历根的每棵子树,再依次用同样方式遍历除去第一棵树的剩余树构成的森林。
2、后序遍历:是先访问森林中第一棵树,后根遍历的方式遍历每棵子树,然后再访问根结点,再依次同样方式遍历除去第一棵树的剩余树构成的森林。

当以二叉链表作为树的存储结构时,树的先根遍历和后根遍历完全可以借用二叉树的前序遍历和中序遍历的算法来实现。

发布了96 篇原创文章 · 获赞 19 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Thera_qing/article/details/104511288