树的基本结构

树的概念及结构

1.1 树的概念

(Tree)是一种非线性的数据结构 ,它是由 n ((( n \\geq 0 )个有限结点组成的一个具有层次关系的集合。

  • 把它叫做"树",是因为其结构形似一棵倒挂的树根朝上,叶朝下
  • 根结点 (Root):树中一个特殊的结点,没有前驱结点
  • 除根结点外,其余结点被分成M(M>0)个互不相交的集合T1、T2、......、Tm,其中每一个集合Ti(1<= i <= m)又是一棵结构与树类似的子树。每棵子树的根结点有且只有一个前驱,可以有0个或多个后继
  • 每棵子树的根结点有且只有一个前驱 (即父结点),但可以有 0 个或多个后继(即子结点)。

树是递归定义的

注意:树形结构中,任意两棵子树之间不能有交集,否则就不是树。


1.2 树的相关概念

术语 定义 示例(假设图中根为 A)
结点的度 一个结点所含子树的个数 A 的度为 6
叶结点 / 终端结点 度为 0 的结点 B、C、H、I 等
非终端结点 / 分支结点 度不为 0 的结点 D、E、F、G 等
父结点 / 双亲结点 若结点 X 有子结点 Y,则 X 是 Y 的父结点 A 是 B 的父结点
子结点 / 孩子结点 若结点 X 有子树,其根即为 X 的子结点 B 是 A 的孩子结点
兄弟结点 具有相同父结点的结点互为兄弟 B 和 C 是兄弟结点
树的度 树中所有结点的度的最大值 树的度为 6
结点的层次 从根开始定义:根为第 1 层 ,其子为第 2 层,依此类推 A:1层,B/C:2层,......
树的高度 / 深度 树中结点的最大层次数 高度为 4
堂兄弟结点 父结点在同一层的结点互为堂兄弟 H 和 I 的父结点(如 E 和 F)若在同一层,则 H 与 I 为堂兄弟
祖先 根到该结点路径上的所有结点 A 是所有结点的祖先
子孙 以某结点为根的子树中的所有结点 所有结点都是 A 的子孙
森林 m ((( m \> 0 )棵互不相交的树组成的集合 多棵树 ⇒ 森林

注:

  • "堂兄弟"强调的是父结点处于同一层,而非是否相邻;
  • 森林可看作是"去掉了根结点的树"------一棵树去掉根后,其各子树构成森林。
  • 树的度与离散数学中图的度有一定区别

1.3 树的表示

树结构比线性表更复杂,不仅要存储结点的数据(值域) ,还要保存结点之间的层次与关联关系

因此,树有多种存储表示方法,常见的包括:

  • 双亲表示法:每个结点记录其父结点的位置;
  • 孩子表示法:每个结点记录其所有子结点;
  • 孩子双亲表示法:同时记录父结点和子结点;
  • 孩子兄弟表示法 (二叉树表示法):每个结点只记录第一个孩子下一个兄弟

在实际应用中,孩子兄弟表示法最为常用,尤其在将普通树转化为二叉树进行处理时非常高效。


孩子兄弟表示法(Left-Child Right-Sibling Representation)

核心思想:

任意一棵树 转换为二叉树形式表示:

  • 每个结点有两个指针:
    • firstChild(或 left):指向第一个孩子
    • nextSibling(或 right):指向紧邻的下一个兄弟
结点结构定义(C语言示例):
c 复制代码
typedef int DataType;

typedef struct TreeNode {
    DataType data;               // 结点数据
    struct TreeNode* firstChild; // 指向第一个孩子
    struct TreeNode* nextBrother; // 指向下一个兄弟
} TreeNode;

如图,使用孩子指针储存子节点,兄弟指针储存同级节点,实现树状存储。

二叉树概念及结构

2.1 二叉树的概念

一棵二叉树 (Binary Tree)是结点的一个有限集合,该集合满足以下两个条件之一:

  1. 空集合(即空树);
  2. 由一个根结点 (root),其中:
    • 左子树和右子树本身也是二叉树
    • 左、右子树有严格顺序之分 ,即使某子树为空,其位置仍有意义。

关键特性:

  • 每个结点最多有两个子结点
  • 子结点分为左孩子 (left child)和右孩子 (right child),顺序不可交换
    (例如:左子树为空、右子树非空 ≠ 右子树为空、左子树非空)

2.3 特殊的二叉树

1. 满二叉树(Full Binary Tree / Perfect Binary Tree)

  • 定义 :一棵深度为 K 的二叉树,如果每一层的结点数都达到最大值,则称为满二叉树。

  • 第 i 层最多有 2^(i-1) 个结点(根为第 1 层);

  • 深度为 K 的满二叉树的总结点数为

    n = 2^K - 1

  • 特点

    • 所有叶子结点都在最底层
    • 除叶子外,每个非叶结点都有两个孩子
    • 结构完全对称、紧凑。

2. 完全二叉树(Complete Binary Tree)

  • 定义 :对于深度为k节点数数是 n个结点的二叉树,若其每个结点的位置都与深度为 K 的满二叉树中编号从 1 到 n 的结点一一对应,则称为完全二叉树。

    • 编号按层序遍历(从上到下、从左到右)进行。
  • 直观理解

    • 除最后一层外,其他层都是满的
    • 最后一层的结点全部靠左排列,不能有"空洞"。
  • 关键性质

    • 叶子结点只可能出现在最后两层
    • 若存在度为 1 的结点,则只能有一个 ,且是左孩子
    • 满二叉树是完全二叉树的特例(当 n = 2^K - 1 时)。
  • 为什么重要

    • 完全二叉树可以高效地用数组存储(无空间浪费);
    • (Heap)等高效数据结构的基础;
    • 支持 O(1) 时间通过下标计算父子关系。

满二叉树 vs 完全二叉树 对比

特性 满二叉树 完全二叉树
是否每层都满? 最后一层可不满
最后一层是否靠左? ---(已满) 必须靠左
是否一定是完全二叉树? 不一定(如右偏树就不是)
能否用数组高效存储? 能(且更通用)

2.5 二叉树的存储结构

二叉树的存储方式主要有两种:顺序存储链式存储。它们各有适用场景和优缺点。


1. 顺序存储(数组实现)

  • 实现方式 :使用数组层序遍历的顺序存储结点。
  • 适用条件仅适合完全二叉树 (或接近完全的二叉树)。
    • 原因:非完全二叉树在数组中会产生大量空洞 (用无效值如 null 填充),造成空间浪费
  • 父子关系通过下标计算 (根结点位于下标 0):
    • 父结点:parent = (i - 1) / 2
    • 左孩子:left = 2 * i + 1
    • 右孩子:right = 2 * i + 2

对于非完全二叉树,也可以使用数组顺序储存,但是需要补齐空的子节点,会造成大量空间浪费

典型应用 (Heap)------因其本质是完全二叉树,故广泛采用数组顺序存储。
一般二叉树不推荐使用顺序存储

  • 特点
    • 物理结构:连续的数组;
    • 逻辑结构:仍是一棵二叉树;
    • 优点:空间紧凑(对完全二叉树)、缓存友好、支持 O(1) 随机访问;
    • 缺点:对普通二叉树空间效率极低。

2. 链式存储(指针/引用实现)

  • 实现方式 :使用链表结构 ,每个结点包含:
    • 数据域(存储结点值);
    • 左指针域(指向左孩子);
    • 右指针域(指向右孩子)。
c 复制代码
typedef struct BinaryTreeNode {
    DataType data;
    struct BinaryTreeNode* left;   // 指向左子树
    struct BinaryTreeNode* right;  // 指向右子树
} BTNode;

优点:结构简单,适用于绝大多数二叉树操作(遍历、构建、删除等);

应用场景:二叉搜索树(BST)、普通二叉树、表达式树等。

相关推荐
kaikaile19952 小时前
A星算法避开障碍物寻找最优路径(MATLAB实现)
数据结构·算法·matlab
今天_也很困2 小时前
LeetCode 热题100-15.三数之和
数据结构·算法·leetcode
思成Codes4 小时前
ACM训练:接雨水3.0——动态接雨水
数据结构·算法
sin_hielo4 小时前
leetcode 2943
数据结构·算法·leetcode
Snow_day.5 小时前
有关平衡树
数据结构·算法·贪心算法·动态规划·图论
mikelv016 小时前
实现返回树状结构小记
java·数据结构
张张努力变强7 小时前
C++类和对象(一):inline函数、nullptr、类的定义深度解析
开发语言·前端·jvm·数据结构·c++·算法
ValhallaCoder7 小时前
Day48-单调栈
数据结构·python·算法·单调栈
Morwit8 小时前
*【力扣hot100】 448. 找到所有数组中消失的数字
数据结构·算法·leetcode