[入门必看]数据结构5.4:树、森林

本文详细介绍了树的三种存储结构——双亲表示法、孩子表示法和孩子兄弟表示法,及其在存储森林时的拓展。同时,探讨了树、森林与二叉树之间的转化方法,并概述了树和森林的遍历策略,包括先根遍历、后根遍历和层次遍历。这些内容对于理解和操作树形数据结构至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


第五章 树与二叉树

小题考频:30
大题考频:8


5.4 树、森林

难度:☆☆☆

知识总览

5.4.1 树的存储结构

在这里插入图片描述

5.4.2 树、森林与二叉树的转化

在这里插入图片描述

5.4.3 树和森林的遍历

在这里插入图片描述


5.4.1 树的存储结构

在这里插入图片描述

树的逻辑结构

在这里插入图片描述

树是一种递归定义的数据结构
一棵树要么是空树,要么至少有一个根结点,根结点的下方可能有零棵或多棵互不相交的子树。

二叉树:一个分支结点最多只能有两棵子树
:一个分支结点可以有多棵子树

如何用顺序存储来存储树这种数据结构?


回顾:二叉树的顺序存储

在这里插入图片描述

二叉树的顺序存储:按照完全二叉树中的结点顺序,将各结点存储到数组的对应位置。数组下标反映结点之间的逻辑关系
在这里插入图片描述

顺序存储二叉树时,结点编号会和完全二叉树对应。
那么这种思路能否推广到普通的树?


如何实现树的顺序存储?

在这里插入图片描述

由于每个分支结点的子树数量不确定,所以没有与之对应的“完全树”,单纯依靠数组下标无法判断结点之间的逻辑关系。

可以发现树中,除了根结点外,其他任意结点都有且只有一个双亲结点(父结点)。

思路:用数组顺序存储各个结点。每个结点对应一个数组下标,在其中保存数据元素、指向双亲结点(父结点)的“指针”

在这里插入图片描述

树的存储1:双亲表示法

在这里插入图片描述

数组元素中,包含两个字段,第一个字段表示数据元素,第二个字段用一个int型变量指明双亲在数组中的下标是多少。
用刚才定义的结构体声明一个数组。
最后记录结点的总数。

拓展:双亲表示法存储“森林”

在这里插入图片描述

双亲表示法的优缺点

在这里插入图片描述

优点:找双亲(父结点)好
缺点:找孩子难,要遍历整个数组
应用场景:找父亲多,找孩子少,Eg.并查集


树的存储2:孩子表示法

在这里插入图片描述

在每个数组在链表元素中,保留一个链表头指针,如果其有孩子,在链表中保存所有孩子结点的编号

在这里插入图片描述

孩子表示法是顺序存储+链式存储结合
一个数组元素中包含data和一个链表CTNode的指针,链表结点中保存孩子的编号以及指向下一个链表结点的指针。
用刚才定义的结构体CTBox声明一个数组,存储各结点的信息。
并记录结点总数和根的位置。

拓展:孩子表示法存储“森林”

在这里插入图片描述

用孩子表示法存储森林,需要记录多个根的位置

孩子表示法的优缺点

在这里插入图片描述

优点:找孩子好
缺点:找双亲(父结点)难,要遍历整个数组
应用场景:找孩子多,找父亲少,Eg.服务流程树【办理业务请按1】


树的存储3:孩子兄弟表示法

在这里插入图片描述

链式实现
结构体包含数据,和两个指针,第一个指针指向第一个孩子,第二个指针指向右边一个兄弟【类似二叉树结点的定义】
采用二叉链表实现

在这里插入图片描述

根结点是A,左指针指向B,右指针指向NULL;
C是B的右边第一个兄弟结点,连到B的右指针,D结点连到C的右指针;
E是B的第一个孩子,连到B的左指针;
F是E的右边第一个兄弟结点,连到E的右指针,G结点连到F的右指针,H连到G的右指针,I连到H的右指针,J连到I的右指针;
K是E的第一个孩子,连到E的左指针。

孩子兄弟表示法形态和二叉树类似。

拓展:孩子兄弟表示法存储“森林”

在这里插入图片描述

把树根C看做B的兄弟,连到B右指针上,以此类推。


5.4.2 树、森林与二叉树的转化

在这里插入图片描述

树->二叉树的转换

用孩子兄弟表示法存储树或者森林的时候会呈现出和二叉树类似的形态。
树、森林与二叉树的转换本质上就是画出用孩子兄弟表示法表示的树和森林。

在这里插入图片描述

树 -> 二叉树转换技巧:
① 先在二叉树中,画一个根结点。
② 按**“树的层序”**依次处理每个结点。

处理一个结点的方法是:如果当前处理的结点在树中有孩子,就把所有孩子结点“用右指针串成糖葫芦”,并在二叉树中把第一个孩子挂在当前结点的左指针下方

Eg1:

A结点:

在这里插入图片描述----->在这里插入图片描述

B结点:
在这里插入图片描述----->在这里插入图片描述

C结点:
在这里插入图片描述

H结点:
在这里插入图片描述

Eg2.
在这里插入图片描述


森林->二叉树的转换

在这里插入图片描述
思路同上。
注意,第一步:森林中各树的根结点视为兄弟,用右指针串起来。
在这里插入图片描述
Eg2.

加粗样式


二叉树->树的转换

在这里插入图片描述
还原A结点:
在这里插入图片描述
以此类推还原。

Eg2.
在这里插入图片描述


二叉树->森林的转换

在这里插入图片描述
原理类似。
注意,先将根节点和一串右指针还原成多棵树的根结点。

Eg2.
在这里插入图片描述


5.4.3 树和森林的遍历

在这里插入图片描述

树的逻辑结构

在这里插入图片描述

有递归特性,可以用递归算法来实现对树的遍历


树的先根遍历

在这里插入图片描述

访问根结点visit(R),接下来用while循环来检查其还有没有下一个没有被访问过的子树。
如果有,那么对子树也采取先根遍历的策略。

树的先根遍历序列与这棵树相应二叉树的先序序列相同。


树的后根遍历

在这里插入图片描述

原理类似,处理完所有子树时访问结点。
树的后根遍历序列与这棵树相应二叉树的后序序列相同。


树的层次遍历

在这里插入图片描述
实现思路和二叉树一样,用一个辅助队列来实现

根结点入队:
在这里插入图片描述
队头元素出队,该元素的孩子依次入队
在这里插入图片描述
重复该过程

尽量横向探索,也叫广度优先遍历。
那么先根遍历和后根遍历,也叫深度优先遍历。


森林的先序遍历

在这里插入图片描述

森林去掉根结点后各子树又组成森林,森林这种数据结构是和树相互递归定义的
可以用递归的思想来遍历森林

首先,访问森林中第一棵树的根结点B
先序遍历第一棵树中根结点的子树森林,E、F两棵树组成的森林
重复第一步,先访问森林中第一棵树的根结点E
遍历E的两个子树森林,即K、L两棵树组成的森林
遍历完K后,再遍历除了第一棵树K之后的剩余的树构成的森林,即L

效果等同于依次对各个树进行先根遍历
可以对各个子树进行一个先序遍历,然后排出一个完整的序列

另一种方法:转换成与之对应的二叉树:
在这里插入图片描述

效果等同于依次对二叉树的先序遍历

森林的中序遍历

在这里插入图片描述
同样可以转换成与之对应的二叉树:
在这里插入图片描述

效果等同于依次对二叉树的中序遍历


知识回顾与重要考点

5.4.1 树的存储结构

在这里插入图片描述

  • 双亲表示法:顺序存储,保存父结点下标,易找父,难找孩
  • 孩子表示法:顺序存储,保存孩子链表头指针(顺序+链式),易找孩,难找父
    在这里插入图片描述
  • 孩子兄弟表示法:二叉链表存储,左孩子右兄弟,形态上和二叉树类似

重要考点:树、森林与二叉树的转换


5.4.2 树、森林与二叉树的转化

在这里插入图片描述

  • 本质上就是用孩子兄弟表示法存储树或森林
  • 存储森林时,将每棵树的根结点视为兄弟
  • Tips:记“本质”,不记方法。方法只是表象,“本质”才是内核。

5.4.3 树和森林的遍历

在这里插入图片描述

  • 对森林的遍历可以转换成对二叉树的遍历
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

H3T

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值