树与二叉树(数据结构)

  • 树的最基本概念(略);
  • 树型结构是一类非常重要的非线性数据结构,因为不是线性的,所以保存时没有数组那么容易和方便。
  • 每颗树都有一个根结点(因此结点数量 n ≥ 1 n \ge 1 n1)。没有父结点的树结点称为根结点;
  • 每个节点都可以有0个或多个子结点,子结点数量为0的结点称为叶节点

相关概念

  • 结点的度:一个结点含有的子结点的个数称为该结点的度;
  • 树的度:一棵树中,最大的结点的度称为树的度;
  • 叶结点或终端结点:度为0的结点称为叶结点;
  • 结点的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推;
  • 树的高度或深度:定义一棵树的根结点层次为1,其他结点的层次是其父结点层次加1。一棵树中所有结点的层次的最大值称为这棵树的深度。
  • 森林:由棵互不相交的树的集合称为森林。

树的存储结构:

  • 树的保存主要以链表的结构保存,下面是3种常用的保存方式:

双亲表示法

  • 定义一个结构体或类,用来保存结点数据以及它的父节点地址。将所有的结点保存成结构体数组,这样方便遍历访问。
  • 也即每个节点设置一个变量保存父节点的地址,根节点的变量值设置为空。
class node {
    int parentIndex;	// 父结点的数组索引值
    Data data;			// 结点数据对象
}

孩子表示法:

  • 每个结点都保存它所有孩子节点的地址,因为不同的结点其孩子节点的数量可能会不一致,所以这里一般采用链表的形式保存孩子节点地址。
  • 也即将双亲表示法中父节点地址替换成链表首地址。
    孩子表示法

]
)

孩子兄弟表示法

  • 该方法又称二叉树表示法,或称二叉链表表示法。
  • 链表中设置两个固定的指针域,第一个指针域指向子一个孩子节点,第二个指针域指向下一个兄弟节点。这样每个结点的指针域都是固定的,方便分配内存空间。
    孩子兄弟表示法

二叉树

  • 二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。
  • 二叉树特点是每个结点最多只能有两棵子树,且有左右之分。
  • 二叉树的递归定义为:二叉树是一棵空树,或者是一棵由一个根节点和两棵互不相交的,分别称作根的左子树和右子树组成的非空树;左子树和右子树又同样都是二叉树。

二叉树图片

  • 在研究二叉树的一般性质是,我们先来研究一下几种特殊的二叉树。

满二叉树

  • 如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树。
  • 除最后一层无任何子节点外,每一层上的所有结点都有两个子结点的二叉树。

满二叉树的性质

  • 从上到下,一个满二叉树每层的节点数分别为:1,2,4,8,16…;容易发现他们都是2的倍数。可以表示为: 2 0 , 2 1 , 2 2 , 2 3 , 2 4 2^0,2^1,2^2,2^3,2^4 20,21,22,23,24…;
  • 也即满二叉树第i层上的结点数为: 2 i − 1 2^{i-1} 2i1。因此深度为k的一个满二叉树,它的叶子节点数量为:

2 k − 1 2^{k-1} 2k1

  • 非叶子节点的数量(前 k − 1 k-1 k1层)为:

2 0 + 2 1 + . . . + 2 k − 2 = 2 k − 1 − 1 2^{0} + 2^{1} + ... + 2^{k-2} = 2^{k-1}-1 20+21+...+2k2=2k11

  • 满二叉树的叶子结点数比非叶子结点数量多一个;
  • 第k层最左边第一个叶子结点的编号为:

( 2 k − 1 − 1 ) + 1 = 2 k − 1 (2^{k-1}-1)+1=2^{k-1} (2k11)+1=2k1

  • 也即如果一个节点的 i ≥ 2 k − 1 i\ge 2^{k-1} i2k1,那么这个节点一定是叶子节点,反之则是非叶子节点。

  • 一个层数为 k k k的满二叉树总结点数为:

2 k − 1 + 2 k − 1 − 1 = 2 k − 1 2^{k-1} + 2^{k-1} - 1 = 2^k - 1 2k1+2k11=2k1

  • 2 k − 1 2^{k}-1 2k1一定是一个奇数,因此满二叉树的节点数量一定是奇数个。
  • 设层数为k的满二叉树的总结点数为n,则他们满足:

2 k − 1 = n k = l o g 2 ( n + 1 ) 2^k - 1 = n\\ k = log_2(n+1) 2k1=nk=log2(n+1)

  • 设某一个结点的编号为 i i i,则它的父节点的编号为: ⌊ i / 2 ⌋ \lfloor i/2 \rfloor i/2,如果该节点有子孙节点( i < 2 k − 1 i < 2^{k-1} i<2k1),则其左孩子节点的编号为: 2 i 2i 2i,右孩子节点的编号为: 2 i + 1 2i+1 2i+1

完全二叉树

  • 一棵深度为k的有n个结点的二叉树,对树中的结点按从上至下、从左到右的顺序进行编号,如果编号为 i ( 1 ≤ i ≤ n ) i(1\le i \le n) i(1in)的结点与满二叉树中编号为i的结点在二叉树中的位置相同,则这棵二叉树称为完全二叉树。
  • 满二叉树算是一种特殊的完全二叉树。

完全二叉树的性质:

  • 具有n个节点的完全二叉树的深度为 ⌊ l o g 2 x ⌋ + 1 \lfloor log_2x \rfloor + 1 log2x+1。推到过程如下:

2 k − 1 ≤ n < 2 k k − 1 ≤ l o g 2 n < k k = ⌊ l o g 2 x ⌋ + 1 2^{k-1} \le n < 2^k \\ k-1 \le log_2n < k \\ k = \lfloor log_2x \rfloor + 1 2k1n<2kk1log2n<kk=log2x+1

  • 我们知道,在满二叉树中,结点 i i i的左孩子节点为 2 i 2i 2i,有孩子结点为 2 i + 1 2i+1 2i+1;所以在完全二叉树中,有:
    • 如果结点的编号满足 2 i ≤ n 2i \le n 2in,,说明其左孩子节点存在,且编号为 2 i 2i 2i
    • 如果结点的编号满足 2 i + 1 ≤ n 2i+1 \le n 2i+1n,,说明其左右孩子节点都存在,且编号分别为 2 i 2i 2i 2 i + 1 2i+1 2i+1
  • 满二叉树的绝大部分性质都适用于完全二叉树,具体的就不细说了。

二叉树的性质

  • 从满二叉树和完全二叉树的性质中,我们可以提炼出一些通用的二叉树性质:
  1. 二叉树的第 i i i层上最多(满二叉树状态下)有 2 i − 1 2^{i-1} 2i1个节点( i ≥ 1 i\ge1 i1)。

  2. 深度为k的二叉树最多(满二叉树状态下)有 2 k − 1 2^k-1 2k1个节点。

  3. 对于任何一颗二叉树T,如果其叶子结点数为 n 0 n_0 n0度为2的非叶子节点数为 n 2 n_2 n2,,则一定有:

n 0 = n 2 + 1 n_0 = n_2 + 1 n0=n2+1

证明过程)设B为分支(边)总数,节点总数为n,度为1的非叶子节点数为 n 1 n_1 n1,则:

  • n = n 0 + n 1 + n 2 n = n_0 + n_1 + n_2 n=n0+n1+n2
  • 从连接向父结点的角度考虑B:由于除根结点外,每个结点有一条边连向父节点,所以有: B = n − 1 B=n-1 B=n1
  • 从连接到孩子节点的角度考虑B:度为2的节点必然由两条边连向左右孩子节点,而度为1的节点只有一条,度为0的节点没有,所以有: B = n 1 + 2 n 2 = n − 1 B = n_1 + 2n_2 = n - 1 B=n1+2n2=n1
  • 结合上面的表达式可以得出: n 0 = n − n 1 − n 2 = n 1 + 2 n 2 + 1 − n 1 − n 2 = n 2 + 1 n_0 = n - n_1 - n_2 = n_1 + 2n_2 + 1 - n_1 - n_2 = n_2 + 1 n0=nn1n2=n1+2n2+1n1n2=n2+1

二叉树的深度遍历

  • 按深度优先搜索对二叉树进行遍历,根据访问当前节点和左右子树的顺序不同,主要分为三种模式:

先序遍历:

  1. 访问根节点(当前节点);
  2. 先序遍历左子树(递归操作);
  3. 先序遍历右子树(递归操作);

中序遍历:

  1. 中序遍历左子树(递归操作);
  2. 访问根节点(当前节点);
  3. 中序遍历右子树(递归操作);

后续遍历:

  1. 后序遍历左子树(递归操作);
  2. 后序遍历右子树(递归操作);
  3. 访问根节点(当前节点);
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值