二叉树——详细学习笔记

怕时间长了自己忘,就记个系统点的笔记吧,赶脚这位老师讲的还是非常好的,感谢。课程传送门

树的基本术语

放个图使更好地理解

结点:数据元素以及指向子树的分支
根结点:非空树中无前驱结点的结点
叶子结点:是度=0的的结点(无后继/无分支/无子树),也叫终端节点
分支结点:后面有分支的结点,因为度不为0,所以也叫非终端结点
内部结点:除根节点以外的分支结点
结点的子树的 称为该结点的孩子,该结点称为孩子的双亲
兄弟结点:有共同双亲的结点
堂兄弟:双亲在同一层的结点
结点的祖先:从根到该结点所经分支上的所有结点
结点的子孙:以某结点为根的子树中的任意结点

结点的度:结点拥有的子树数(分支数)
树的度:树内各结点的度的最大值
树的深度:树中结点的最大层次,也叫高度
有序树:树中结点的各子树从左到右有次序
无序树:无次序,无论每个子树在什么位置,都是这一棵树的树

森林:是m(m>=0)棵互不相交的树的集合
关系:把根结点删除,树就变成了森林;一棵树可以看成一个特殊的森林(即一棵树的森林);给森林的个子树加上一个双亲结点,森林就变成了树。
树一定是森林,
森林不一定是森林。

二叉树

定义:二叉树是n(n>=0)个结点的有线集,它或是空集,或者是由一个根结点及两棵互不相交的分别称为这个根的左子树和右子树的二叉树组成
特点:
每个结点最多有俩孩子(二叉树中不存在度大于2的结点)
子树有左右之分,次序不能颠倒
可以是空集合,根可以有空的左子树或右子树
数和二叉树的关系与区别如下:
在这里插入图片描述就比如下面这个问题

但是虽然树和二叉树的概念不同,但是树的基本术语对二叉树都适用
然后二叉树的五种基本形态:

两种特殊形式的二叉树

满二叉树

定义:一棵深度为k且有2^k-1个结点的二叉树
特点:每一层上的结点数都是最大结点数(即为满),叶子结点都在最底层

完全二叉树

深度为k的具有n个结点的二叉树,当且仅当其每一个结点都与深度为k的满二叉树中编号为1~n的结点一一对应是,称之为完全二叉树
关系:在满二叉树中,从最后一个结点开始,连续去掉任意个结点,都是一课完全二叉树

二叉树的性质

二叉树具有以下五个性质:

  1. 在二叉树的第i(i>=1)层最多有2^(i - 1)个结点。
  2. 深度为k(k>=0)的二叉树最少有k个结点,最多有2^k-1个结点。
  3. 对于任一棵非空二叉树,若其叶结点数为n0,度为2的非叶结点数为n2,则n0 = n2 +1。
  4. 具有n个结点的完全二叉树的深度为int_UP(log(2,n+1))。
  5. 如果将一棵有n个结点的完全二叉树自顶向下,同一层自左向右连续给结点编号1,2,3,......,n,然后按此结点编号将树中各结点顺序的存放于一个一维数组,并简称编号为i的结点为结点i( i>=1 && i<=n),则有以下关系:
    (1)若 i= 1,则结点i为根,无父结点;若 i> 1,则结点 i 的父结点为结点int_DOWN(i / 2);
    (2)若 2*i <= n,则结点 i 的左子女为结点 2*i;
    (3)若2*i<=n,则结点i的右子女为结点2*i+1;
    (4)若结点编号i为奇数,且i!=1,它处于右兄弟位置,则它的左兄弟为结点i-1;
    (5)若结点编号i为偶数,且i!=n,它处于左兄弟位置,则它的右兄弟为结点i+1;
    (6)结点i所在的层次为 int_DOWN(log(2,i))+1。

二叉树的存储结构

顺序存储结构

实现:按满二叉树的结点层次编号,依次存放二叉树中的数据元素。例:

链式存储结构


代码实现:

typedef struct BiNode{
  TElemType  data;
  struct BiNode  *lchild,*rchild
}BiNode,*BiTree;

思考:


引申一下三叉链表,它更方便找前驱结点,然后在n个结点的三叉链表中,是有n+2个空指针域

二叉树遍历算法的实现

根据根的遍历位置可分以下三种方式:
先序二叉树 DLR
中序二叉树 LDR
后序二叉树 LRD


由遍历的序列确定二叉树

实例一:

实例二:

关键 – 这个口诀非常实用:

先序根在首
后序根在末
定根之后分小组
中序断定左和右

遍历二叉树的递归算法



时间效率:O(n) 每个结点只访问一次
空间效率:O(n) 栈占用的最大空间

递归算法的过程

以先序为例:
调用自己,pre(T->L)即此时根节点为左孩子,并作为根输出,再依次往下遍历

遍历二叉树的非递归算法

以中序为例:

层次遍历(队列)


在这里插入图片描述

简单点来说就是进a,(出a,进b,f),(出b,进c,d),(出f,进g),(出c,进空),(出d,进e),(出g,进h),(出e,进空),(出h,进空),故顺序为 abfcdgeh。

代码实现:

二叉树的遍历算法应用

建立二叉树的算法



首先先序序列为ABCDEGF的二叉树是不为一种的
然后我们在建立二叉树算法的时候,一般先把它补全
再用特殊字符表示出来,比如#

这个算法就是按输入的字符顺序读入,执行这个程序,可以理解为(((( ))))),一层一层的。
首先读入A,进行步骤一(不为#,进入else,开辟结点空间,生成根结点),然后调用自己,构造左子树,读入B,步骤一,此时B为根结点,接着调用自己,构造左子树,读入C,步骤一;
这时不一样了,因为构造左子树后,读入的字符为#,就 return OK了,即返回到生成C根结点时,调用自己,构造右子树,读入的还是#,所以return OK(C的一整层就结束了);
这时返回到的是B为根结点的下面,然后调用自己,构造左子树,读入D,步骤一,D为根结点,再调用自己,构造左子树,读入E,步骤一,E为根结点,再调用自己,构造左子树;
又读入#了,所以退出这一小层,到E为根结点的下面构造右子树,读入G,步骤一,G为根结点后,由于读入两个#,所以退到D为根结点的下面,构造右子树,步骤一,读入###后到了A为根结点的右子树为空。

复制、求结点数、求叶子结点数

用递归呢,就是一层一层的调用,这个理解了,后面这几种算法都很容易

复制二叉树

计算二叉树深度

计算二叉树结点数


感觉这几个算法都大同小异,因为原理一样(递归思想),二叉树用递归真的是太合适了

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值