数据结构-树详解

树是n个结点的有限集。n = 0时称为空树。在任意一颗非空树中:

  • 有且仅有一个特定的称为根的节点
  • 当n > 1时,其余节点可分为m (m > 0)个互不相交的有限集,其中每一个集合本身又是一棵树,并且称为根的子树
节点分类

节点有用的子树数称为节点的。度为0的节点称为叶节点或终端节点;度不为0的节点称为非终端节点或分支节点。除根节点之外,分支节点也称为内部节点。树的度是树内各节点的度的最大值。

节点的层次从根开始定义起,根为第一层,根的孩子为第二层。若某节点在第一层,则其子树的根就在第l+1层。其双亲在同一层的节点互为堂兄弟。树种节点的最大层次称为树的深度或高度。

如果将树中节点的各子树看成从左至右是有次序的,不能互换的,则称该树为有序树,否则称为无序树

森林是m(m >= 0)课互不相交的树的集合。对树中每个节点而言,其子树的集合即为森林。

对比线性表和树的机构:
线性结构:

  • 第一个数据元素:无前驱
  • 最后一个数据元素:无后继
  • 中间元素:一个前驱一个后继

树结构:

  • 根节点:无双亲,唯一
  • 叶节点:无孩子,可以多个
  • 中间节点:一个双亲多个孩子
树的存储结构
双亲表示法

树这种结构,除了根节点外,其余每个节点,它不一定有孩子,但是一定有且仅有一个双亲。

我们假设以一组连续空间存储树的节点,同时在每个节点中,附设一个指示器指示其双亲节点到链表中的位置。也就是说,每个节点除了知道自己是谁以外,还知道它的双亲在哪里。

这样想找它的父节点就很简单了,但是如果想找一个节点的子节点呢,那么就要遍历整个树,显示很麻烦,我们可以在加一个指针,表示他的第一个子节点的位置,这样就容易找到了,如果还有其他的子节点呢,我们只要找到一个子节点,因为其他子节点和这个子节点的父节点相同,那么就很容易找到其他的子节点了

孩子表示法

由于树中每个节点可能有多颗子树,可以考虑用多重链表,即每个节点有多个指针域,其中每个指针指向一颗子树的根节点,我们把这种方法叫做多重链表表示法。不过,树的每个节点的度,也就是它的孩子个数是不同的。所以可以设计两种方案来解决。

比如树的度是3,那么每个节点就增加三个指针域用来表示每个节点的孩子,但是这样做会浪费空间,因为有的节点可能没有三个孩子,只有一个。

那么我们可以这个节点有几个孩子就有几个指针域,但是这样一来我们需要增加一个参数用来表示树的度。

那我们还可以换一种方法,用一个单链表来表示孩子节点,A节点有B,C两个孩子节点,那么A的指针就指向单链表的头结点,单链表里面有两个节点,B和C。

二叉树

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

二叉树的特点
  • 每个节点最多有两颗子树,所以二叉树中不存在度大于2的节点。注意不是只有两颗子树,而是最多有。没有子树或者有一颗子树都是可以的
  • 左子树和右子树是有顺序的,次序不能任意颠倒。就像人是双手、双脚,但显然左手、左脚和右手、右脚是不一样的,右手戴左手套、右脚穿左鞋都会极其别扭和难受。
  • 即使树中某节点只有一颗子树,也要区分它是左子树还是右子树。
二叉树五种基本形态
  • 空二叉树。
  • 只有一个根节点
  • 根节点只有左子树
  • 根节点只有右子树
  • 根节点既有左子树又有右子树。
特殊二叉树

斜树
斜树一定要是斜的,但是往哪斜是有讲究的。所有的节点都只有左子树的二叉树叫左斜树。所有节点都是只有右子树的二叉树叫右斜树。这两者统称为斜树。

满二叉树
在一棵二叉树中,如果所有分支节点都存在左子树和右子树,并且所有叶子都在同一层上,这样的二叉树称为满二叉树。
单是每个节点都存在左右子树,不能算是满二叉树。因此满二叉树的特点有:

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

完全二叉树
对一颗具有n个节点的二叉树按层序编号,如果编号为i(1<=i<=n)的节点与同样深度的满二叉树中编号为i的节点在二叉树中位置完全相同,则这个二叉树称为完全二叉树。
满二叉树一定是一颗完全二叉树,但完全二叉树不一定是满的。

完全二叉树的特点:

  • 叶子节点只能出现在最下两层。
  • 最下层的叶子一定集中在左部连续位置。
  • 倒数二层,若有叶子节点,一定都在右部连续位置。
  • 如果节点度为1,则该节点只有左边孩子,即不存在只有右子树的情况
  • 同样节点数的二叉树,完全二叉树的深度最小。
二叉树的性质
  • 在二叉树的第i层上至多由2的i-1次方个节点(i >= 1)
  • 深度为k的二叉树至多有2的k次方-1个节点(k >= 1)
  • 对于任何一个二叉树,叶子节点数 = 度为2的节点数 + 1;节点总数 = 叶子节点数 + 度为1的节点数 + 度为2的节点数;连接线数 = 节点总数 - 1
二叉树的存储结构
顺序存储

可以用数字下标编号对于二叉树序号来存储,因为完全二叉树和满二叉树的序号都是连续的,可以很好的存储,但是其他的就不行了,虽然可以对应序号的不存在就把对应下标置空,但是太浪费空间

链式存储

用一个数据域data来存储数据,一个lchild来存储左边孩子的指针,一个rchild来存储右边孩子的指针

二叉树的遍历
前序遍历

规则是若二叉树为空,则空操作返回,否则先访问根节点,然后前序遍历左子树,再前序遍历右子树。 根 -》左 -》 右

中序遍历

规则是若二叉树为空,则空操作返回,否则先访问根节点的左子树,再访问根节点,再右子树。 左 -》 根 -》右

后序遍历

左 -》 右 -》 根

层序遍历

按层遍历,每层从左到右遍历完在遍历下一层

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二叉查找在查找中有重要的应用。它是一种满足以下两个条件的二叉:对于中的每个节点X,它的左子中所有项的值都要小于X中的项;对于中的每个节点Y,它的右子中所有项的值都要大于Y中的项。这种特点使得二叉查找在查找操作中非常高效。 一种常见的应用是在二叉排序中实现中序遍历,可以通过中序遍历得到一个升序的数列。在给定的代码中,InOrder函数通过递归实现了二叉排序的中序遍历。它将的左子进行中序遍历,然后将根节点的值存入数组,最后再对的右子进行中序遍历。isOrder函数则用于判断一个数列是否升序。它通过遍历数列中的每个元素,判断当前元素是否大于前一个元素来判断数列是否升序。 因此,二叉查找的应用主要是用于高效的查找操作,并且可以通过中序遍历获取升序的数列。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [C++二叉查找实现过程详解](https://download.csdn.net/download/weixin_38727980/13758023)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [数据结构-二叉查找的应用](https://blog.csdn.net/Junds0/article/details/121791335)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值