树及二叉树

树的基本术语

结点的度:结点拥有的子树数称为结点的度(Degree)。度为0 的结点称为叶结点(Leaf) 或终端结点;度不为0 的结点称为非终端结点或分支结点。
树的度:树的度是树内各结点的度的最大值。如下图所示,因为这棵树结点的度的最大值是结点D 的度,为3 ,所以树的度也为3 。
这里写图片描述
结点的子树的根称为该结点的孩子(Child) ,相应地,该结点称为孩子的双亲(Parent)。同一个双亲的孩子之间直称兄弟(Sibling) 。结点的祖先是从根到该结点所经分支上的所有结点,以某结点为根的子树中的任一结点都称为该结点的子孙。
结点的层次( LeveI) 从根开始定义起,根为第一层, 根的孩子为第二层。树中结点的最大层次称为树的深度( Depth)或高度。
如果将树中结点的各子树看成从左至右是有次序的,不能互换的,则称该树为有序树,否则称为无序树。
森林( Forest) 是m (m >= 0) 棵互不相交的树的集合。对树中每个结点而言,其子树的集合即为森林。

树的存储结构

三种表示法:双亲表示法、孩子表示法、孩子兄弟表示法
双亲表示法:在每个结点中,附设一个指示器指示其双亲结点到链表中的位置,其结构如下所示:
这里写图片描述
其中data是数据域,存储结点的数据信息。而parent是指针域,存储该结点的双亲在数组中的下标
树双亲表示法,并加了长子域

孩子表示法:把每个结点的孩子结点排列起来,以单链表作存储结构,则n个结点有n个孩子链表,如果是叶子结点则此单链表为空。然后n个头指针又组成一个线性表,采用顺序存储结构,存放进一个一维数组中,如下所示
双亲孩子表示法

孩子兄弟表示法:任意一棵树,它的结点的第一个孩子如果存在就是唯一的,它的右兄弟如果存在也是唯一的。因此,我们设置两个指针,分别指向该结点的第一个孩子和此结点的右兄弟。结点结构如下所示:

这里写图片描述实现方法

这种表示法,给查找某个结点的某个孩子带来了方便,只需要通过firstchild找到此结点的长子,然后通过长子结点的rightsib找到它的二弟,接着一直下去,直到找到具体的孩子。如果想找双亲的话,可以增加一个parent指针域来解决快速查找双亲的问题。这个表示法最大的好处是它把一棵复杂的树变成了一棵二叉树。

二叉树的定义与特点

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

二叉树的特点

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

二叉树具有五种基本形态

  1. 空二叉树
  2. 只有一个根结点
  3. 根结点只有左子树
  4. 根结点只有右子树
  5. 根结点既有左子树又有右子树

问题:如果是有三个结点的树,有几种形态?如果是有三个结点的二叉树,又有几种形态?(2,5)

特殊二叉树
1.斜树:所有的结点都只有左子树的二叉树叫左斜树。所有结点都是只有右子树的二叉树叫右斜树。这两者统称为斜树。其特点是每一层都只有一个结点,结点的个数与二叉树的深度相同。

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

  • 叶子只能出现在最下一层,出现在其他层就不可能达成平衡。
  • 非叶子结点的度一定是2,否则就是“缺胳膊少腿”了。
  • 在同样深度的二叉树中,满二叉树的结点个数最多,叶子数最多。

3.完全二叉树:对一棵具有n个结点的二叉树按层序编号,如果编号为 i(1=< i <=n)的结点与同样深度的满二叉树中编号为 i 的结点在二叉树中位置完全相同,则这棵二叉树称为完全二叉树。如下图所示:
完全二叉树
完全二叉树的特点:

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

注意“完全”和“满”的差异,满二叉树一定是一棵完全二叉树,但完全二叉树不一定是满二叉树。
判断某二叉树是否是完全二叉树的办法,那就是看着树的示意图,心中默默给每个结点按照满二叉树的结构逐层顺序编号,如果编号出现空挡,就说明不是完全二叉树,否则就是。

二叉树的性质

  1. 在二叉树的第 i 层上至多有2^(i -1) 个结点(i >= 1 ) 。(通过数学归纳法论证)
  2. 深度为 k 的二叉树至多有2^k - 1 个结点(k >= 1)。
  3. 对任何一棵二叉树T,如果其终端结点数为n0,度为2 的结点数为n2,则n0 = n2 + 1 。(终端结点数其实就是叶子结点数,而一棵二叉树, 除了叶子结点外,剩下的就是度为1或2的结点数了,我们设n1 为度是1 的结点数。则树T 结点总数n=n0 +n1 +n2 。)
  4. 具有n 个结点的完全二叉树的深度为[ log2(n) ]+ 1 ( [ x ]表示不大于 x 的最大整数)
  5. 如果对一棵有 n 个结点的完全二叉树(其深度为( [ log2(n) ]+ 1 ) 的结点按层序编号(从第1 层到第[ log2(n) ]+ 1 层,每层从左到右) ,对任一结点 i(1=< i<=n),有:
    (1)如果 i =1 ,则结点 i 是二叉树的根,无双亲;如果 i>1 ,则其双亲是结点 [i /2]
    (2)如果 2i > n,则结点 i 无左孩子(结点 i 为叶子结点) ;否则其左孩子是结点2i 。
    (3)如果 2i+1> n,则结点 i 无右孩子;否则其右孩子是结点2i +1。

二叉树的存储结构

两种方式:

  1. 二叉树顺序存储结构:用一维数组存储二叉树中的结点,井且结点的存储位置,也就是数组的下标要能体现结点之间的逻辑关系,比如~亲与孩子的关系,左右兄弟的关系等。
    完全二叉树顺序存储
    考虑一种极端的情况,一棵深度为k 的右斜树,它只有k 个结点,却需要分配2^k - 1个存储单元空间,这显然是对存储空间的浪费。所以,顺序存储结构一般只用于完全二叉树

2.二叉链表:二叉树每个结点最多有两个孩子,设计一个数据域和两个指针域的链表叫做二叉链表。
这里写图片描述这里写图片描述
其中data是数据域, lchild 和 rchild 都是指针域,分别存放指向左孩子和右孩子的指针。就如同树的存储结构中讨论的一样,如果有需要,还可以再增加一个指向其双亲的指针域,那样就称之为三叉链表。

猜你喜欢

转载自blog.csdn.net/qq_33461648/article/details/80034701