树是一类非线性数据结构,是以分支关系定义的层次结构

数的基本概念

树的定义

树是有n(n>=0)个结点的有限集。在任意一个非空树中

  1. 仅有一个根结点;
  2. 当n>1时,其余结点可分为m(m>0)个互不相交的有限集T1,T2,……Tm,其中每个集合本身又是一棵树,并称为根的子树。

基本术语

结点,结点的度、叶子/终端节点、分支/非终端结点、内部结点、树的度、孩子结点、双亲结点、兄弟结点、祖父结点、堂兄弟结点、结点的层次、树的高度/深度、有序树、无序树、路径和路径长度、森林。

树的性质

  1. 树的结点数等于所有结点的度数+1.
  2. 度为m的树第i层最多有mi-1个结点(i>=1)
  3. 高度为h的m叉树至多有(mh-1)/(m-1)个结点
  4. 具有n个结点的m叉树的最小高度为[logm(n(m-1)+1)]

树的存储结构

用存储完全二叉树的方式存储非完全二叉树有时候太浪费空间了,因此对于一般的树需要使用另外的结构来存储

双亲表示法

使用数组存储,每个数组元素包括数据域和指针域,指针域指向双亲结点。

这种方式好处是节省空间,寻找某双亲结点可以在常量时间内完成。

孩子表示法

以数组存储每个结点,把该结点的孩子结点排列起来用单链表链接到一起。数组数据元素包含数据域和指针域。指针域指向链表的第一个元素。

也可以在数组元素中多加一个指针,指向双亲。

孩子兄弟表示法

这种方法才是需要重点掌握的,因为它将树与二叉树联系起来了。

存储结点的结构包含三部分,firstchild data nextchild。firstchild指向左孩子,nextchild指向右边第一个兄弟。

其实也是一个二叉链(见后面)。

二叉树

二叉树是树研究的重点。

二叉树的定义

二叉树的每个结点最多含有两棵子树,不存在度大于2的结点,并且二叉树的子树有左右之分

二叉树的形态

一共五种。空、子树为空、左子树为空、右子树为空、左右子树都不为空

二叉树的性质

  1. 二叉树的第i层最多有2i-1个结点。
  2. 深度为k的二叉树至多有2i-1个结点
  3. 对于任何一棵二叉树,若终端结点个数为n0,度为二的结点个数为n2,则必有:n0 = n2+1

特殊二叉树

满二叉树

深度为k,且有2i-1个结点的二叉树。特点是每一层的结点都为最大结点数,结点编号从根节点开始,从上往下,从左往右。

完全二叉树

深度为k,有n个结点的二叉树,当且仅当其中每一个结点的编号都与深度为k的满二叉树的结点编号一致时,称为完全二叉树。也就是说完全二叉树只有当上一层完全排满时才会往下一层排。

完全二叉树的特点
  1. 叶子节点只出现在最后两层
  2. 对任一结点,其右分支下的子孙结点最大层次为l,则左分支下的结点最大层次为 l 或者 l+1。
完全二叉树性质
  1. 具有n个结点的完全二叉树深度为[log2n]+1
  2. 如果对一棵有n个结点的完全二叉树的结点按层序编号,则对任一结点有
    (1)若i为1,则i为root结点且无双亲。若i>1,则其双亲结点时[i/2]。
    (2)若2i>n,则i无左孩子(叶子节点),否则其左孩子结点是2i
    (3)若2i+1>n,则i无右孩子(不一定为叶子结点),否则其右孩子结点为2i+1

二叉树的存储

一般存储结构都包含顺序存储和链式存储。

顺序存储

用一组地址连续的存储单元依次从上而下,从左而右存储完全二叉树的结点元素,即编号为 i 的元素存在 i-1位置。如果是一般二叉树采用完全二叉树的形式存储,空位补零。

可以看到,对于一般二叉树来说,可能会浪费相当大的内存,因此一般只有完全二叉树才使用顺序存储。

链式存储结构

链式存储采用的结构有二叉链表和三叉链表。二叉链表包含三个域,数据域、左右子树指针域。三叉链表在二叉链表的基础上加了一个双亲结点指针域,目的是为了方便找到双亲结点。

在n个结点的二叉链表中含有n+1个空链域。为什么是n+1个空链域?n个结点的二叉链表,链域一共是2n个,其中有指向子树的有n-1个,剩下的就是n+1个NULL链域。

这些空链域是有用处的。

二叉树的遍历

遍历的意思是按照某条搜索路径访问树中的每一个结点,使得每个结点均被访问一次,并且只被访问一次。树的遍历有四种形式

先序遍历

NLR

中序遍历

NLR

后序遍历

LRN

层次遍历

从上往下,从左往右依次遍历。层次遍历需要借助队列。

树的遍历的时间复杂度为O(n)。

知道先序/后序/层次遍历顺序+中序遍历顺序都能唯一确定一棵二叉树。必须要知道中序遍历

线索二叉树

线索二叉树的提出是为了让树的遍历变得更加简单,前面说过:在n个结点的二叉链表中含有n+1个空链域;线索二叉树就是让这n+1个空链域指向该结点的直接前驱结点和直接后驱结点的,这样出现了一个问题,就是怎么判断链域指向的是子树还是前驱/后驱结点呢?因此需要一个标志位。

线索二叉树的结点结构:ltag、lchild、data、rchild、rtag
当ltag=0时,lchild指向子树;当ltag=1时,lchild指向前驱结点。同理rtag、rchild。

其中指向前驱和后继的指针称为线索。加上二叉树称为线索二叉树。从线索二叉树的定义可以看出,对一颗线索二叉树遍历只要找到第一个结点,然后一直找rchild就可以了,直到为NULL。线索二叉树主要是为访问运算服务的。

线索化

线索二叉树的线索化就是让二叉树的空指针指向下一个结点的过程。对某二叉树以某种次序遍历使其变为线索二叉树的过程就称为线索化。

树、二叉树、森林

森林与二叉树的转换

为什么能转换?

森林是由树组成的,前面说过树的孩子兄弟存储结构与二叉树的二叉链表结构一样,区别就是第二个指针域的含义不同。将含义转换一下就能将一个普通树变成二叉树了,并且这棵二叉树一定没有右子树。将森林中除了第一棵树之外的树换成的二叉树排在前一棵树的右子树上,就是将森林转换为二叉树。

树和森林的遍历

树的遍历

树的遍历包括先根遍历和后根遍历。

先根遍历是从根节点开始的遍历;后根遍历是最后遍历根节点的方式。

森林的遍历

森林的遍历包括先序遍历和中序遍历。

森林的中序遍历 对应 二叉树的先序遍历 对应 树的先根遍历
森林的中序遍历 对应 二叉树的中序遍历 对应 树的后根遍历

树和二叉树的应用

二叉排序树(BST)、平衡二叉树(AVL)和赫夫曼树(Huffman)

参考资料

严蔚敏《数据结构》
王道数据结构单科书

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值