二叉树的概念|满二叉树与完全二叉树|二叉树的性质|二叉树的存储结构

发布时间:2024年01月17日

前言

在数据结构中树的用途其实并不大,用得更多的其实是二叉树。所以在本章我们将详细讲解二叉树。

一、二叉树的概念及结构

1、概念

一颗二叉树是结点的一个有限集合,该集合:

  • 或者为空
  • 或者由一个根节点加上两颗(互不相交)别称为左子树和右子树的二叉树组成

2、结构

在这里插入图片描述

如图我们可知,二叉树的特点:

  • 二叉树不存在度大于2的结点。可以理解为是一颗计划生育的树。
  • 二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树

注意:对于任意的二叉树都是由以下几种情况复合而成的:

在这里插入图片描述

二、特殊的二叉树

1、斜树

顾名思义,斜树就一定要是斜的,但是往哪边斜也是有区别的:

  • 左斜树:所有的结点都只有左子树的二叉树叫做左斜树。
  • 右斜树:所有的结点都只有右子树的二叉树叫做右斜树。

在这里插入图片描述
如图我们可知斜树的特点:

  • 每一层都只有一个结点,结点的个数与二叉树的深度相同。
  • 斜树的结构与线性表一样

2、满二叉树

一个二叉树,如果每一个层的结点数都达到最大值(即结点的度为2),则这个二叉树就是满二叉树。

在这里插入图片描述

tip:

  • 深度为K的满二叉树有2^k-1个结点
    在这里插入图片描述
  • 非叶子结点的度一定是2
  • 叶子结点只能出现在最下一层
  • 在同样深度的二叉树中,满二叉树的结点数最多,叶子数最多

3、完全二叉树

对于深度为K的,有n个结点的二叉树,按层序编号,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点——对应时称之为完全二叉树。

完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树引出来的。

注意:满二叉树 != 完全二叉树,但是满二叉树是一种特殊的完全二叉树。

在这里插入图片描述

tip:

  • 完全二叉树前K-1层都是满的,最后一层可能不满,但是最后一层要求从左到右是连续的。
  • 完全二叉树中,N1(结点度为1)要么是1(且该结点只有左孩子,即不存在只有右孩子的情况),要么是0。
  • 深度为K的完全二叉树,节点数量的范围:[2^(K-1), 2 ^k-1]
    在这里插入图片描述
  • 同样节点数的二叉树,完全二叉树的深度最小

三、二叉树的性质

  1. 若规定根节点的层数为1,则一颗非空二叉树的第i层上最多有2^(i-1)个结点。
  2. 若规定根节点的层数为1,则**深度为h的二叉树的最大结点数是2^h-1。
  3. 对任何一颗二叉树,如果度为0其叶结点个数为n0,度为2的分支结点个数为n2,则有n0 = n2 + 1。(度为0的永远比度为2的多一个)
    在这里插入图片描述
  4. 若规定根节点的层数为1,具有n个结点的满二叉树的深度h,如下图所示:
    在这里插入图片描述

四、二叉树的存储结构

二叉树一般可以使用两种结构存储,一种顺序存储,一种链式存储。

1、顺序存储

顺序结构存储就是使用数组存储, 一般使用数组 只适合表示完全二叉树, 因为不是完全二叉树会有空间的浪费。

在现实的使用中只有堆才会使用数组来存储二叉树,关于堆我们会在后续详细讲解。

二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树。

在这里插入图片描述
tip:

  • 顺序存储,一般是按照层序对所有结点从0开始编号用数组顺序存储。(因为数组的下标从0开始所以从0开始编号)
  • 数组下标体现了结点之间的逻辑关系
    • parent = (child - 1)/ 2
    • leftchild = parent * 2 + 1
    • rightchild = parent * 2 + 2
  • 数组存储表示二叉树只适合完全二叉树,不适合非完全二叉树,因为会浪费很多空间。

2、链式存储

二叉树的链式存储结构是指,用链表来表示一颗二叉树,即用链来指示元素的逻辑关系。

通常的方法是链表中的每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址。

链表结构又分为二叉链和三叉链,现在我们学习中一般都是二叉链,后面学到高阶数据结构如红黑树等才会用到三叉链。

在这里插入图片描述
代码示例:

//重命名结点数据域类型
typedef int BTDataType;

//二叉链
struct BinaryTreeNode
{
	struct BinaryTreeNode* _pLeft;//指向当前结点左孩子
	struct BinaryTreeNode* _pRight;//指向当前结点右孩子
	BTDataType _data;//当前结点值域
};

//三叉链
struct BinaryTreeNode
{
	struct BinaryTreeNode* _pParent;//指向当前结点的双亲
	struct BinaryTreeNode* _pLeft;//指向当前结点左孩子
	struct BinaryTreeNode* _pRight;//指向当前结点右孩子
	BTDataType _data;//当前结点值域
};
文章来源:https://blog.csdn.net/wangjiushun/article/details/135599863
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。