408数据结构-树与森林 自学知识点整理

前置知识:树的基本概念与性质


树的存储结构

树既可以采用顺序存储结构,又可采用链式存储结构。但无论采取哪种方式,都要求能够唯一地反映树中各结点之间的逻辑关系。

1. 双亲表示法

这种存储结构采用一组连续空间来存储每个结点,同时在每个结点增设一个伪指针,指示其双亲结点在数组中的位置。

#define MAX_TREE_SIZE 100
typedef struct ElemType {int value;
}ElemType;//预处理typedef struct {ElemType data;int parent;//双亲位置域
}PTNode;
typedef struct {//树的类型定义PTNode nodes[MAX_TREE_SIZE];//双亲表示int n;//结点数
}PTree;

双亲表示法利用了除根结点以外每个结点只有唯一双亲的性质,优点是可以很快地得到每个结点的双亲结点,但缺点也很明显,求结点的孩子时需要遍历整个结构。
使用双亲表示法存储树时,删除结点共有两个方法:

  • 一是直接把需要删除的结点 p a r e n t parent parent值置 − 1 -1 1,表示当前结点为空(根结点默认存放在 n o d e s [ 0 ] 的位置 nodes[0]的位置 nodes[0]的位置,且 p a r e n t parent parent值也为 − 1 -1 1,需要特别判断)。但是这种方法在遍历找孩子时,会使得遍历过程要经过一个或多个空结点,徒增时间复杂度。
  • 二是把需要删除的结点和数组末尾元素交换,然后结点数n--。这种方法要优于方法一。

2. 孩子表示法

孩子表示法是将每个结点的孩子视为一个线性表,且以单链表作为数据结构,这样 n n n个结点就有 n n n个孩子链表(叶结点的孩子链表视为空表)。

struct CTNode {//单链表(B站弹幕说是邻接表)int child;//孩子节点在数组中的位置struct CTNode* next;//下一个孩子
};
typedef struct {ElemType data;struct CTNode* firstChild;//第一个孩子
}CTBox;
typedef struct {CTBox nodes[MAX_TREE_SIZE];//孩子表示法int n, r;//结点数和根的位置
}CTree;

与双亲表示法相反,孩子表示法寻找结点孩子的操作非常方便,但是寻找双亲的操作则需要遍历 n n n个结点中孩子链表指针域所指向的 n n n个孩子链表。同样的,可以顺着这个思路思考,如何实现孩子表示法存储的树的增删查改等基本操作。

3.孩子兄弟表示法⭐

孩子兄弟表示法又称二叉树表示法,即以二叉链表作为树的存储结构。孩子兄弟表示法使每个结点包括三部分内容:结点值、指向结点第一个孩子结点的指针,以及指向结点下一个兄弟结点的指针。

typedef struct CSNode {//孩子兄弟表示法ElemType data;//数据域struct CSNode* firstchild, * nextsibling;//第一个孩子和右兄弟指针
}CSNode, * CSTree;

使用这种方法最大的优点就是可以实现将树转换为二叉树的操作,优缺点与二叉树的链式存储结构相同,这里不再展开。

树、森林与二叉树的相互转换

从物理结构上看,树的孩子兄弟表示法和二叉树的二叉链表表示法是相同的。因此可以用同一存储结构的不同解释将一棵树转换为二叉树。

1 ) 1) 1)树转换为二叉树

树转换为二叉树的规则:每个结点的左指针指向它的第一个孩子,右指针指向它在树中的相邻右兄弟,这个规则也称“左孩子右兄弟”。由于根结点没有兄弟,因此树转换得到的二叉树没有右子树,如图所示。 (图片来自王道考研408数据结构2025)
图片来自王道考研408数据结构2025
树转换为二叉树的画法:
①在兄弟结点之间加一条线;
②对每个结点,只保留它与第一个孩子的连线,与其他孩子的全部抹掉;
③以树根为轴心,顺时针旋转45°。
二叉树转换为树逆着来就行。

2 ) 2) 2)森林转换为二叉树

森林转换为二叉树的规则与树类似,只需要把每一棵树的根结点都看成兄弟,依次连在第一棵树根结点的右子树上即可。
森林转换为二叉树的画法:
①将森林中的每棵树转换成相应的二叉树;
②每棵树的根也可视为兄弟关系,在每棵树的根之间加一根连线;
③以第一棵树的根为轴心,顺时针旋转45°。
二叉树转换为森林同样逆着来就行,这里就不再展开。


树和森林的遍历

前置知识:二叉树的遍历

1. 树的遍历

树的遍历是指用某种方式访问树中的每个结点。主要有两种方法:

1 ) 1) 1)先根遍历。若树非空,则按如下规则遍历:
  • 先访问根结点。
  • 再依次遍历根结点的每棵子树,遍历子树时仍遵循先根后子树的规则。
void Visit(CSNode* T) {cout << T->data.value << " ";return;
}void PreOrder(CSTree T) {//先根遍历(使用孩子兄弟表示法)if (T != NULL) {Visit(T);//访问根结点CSTree C = T->firstchild;//C记录当前树根结点的第一个孩子do {//首先对以C为根的子树进行先根遍历PreOrder(C);C = C->nextsibling;//再依次对C的右兄弟为根的子树进行先根遍历} while (C != NULL);//当C还有其他右兄弟时循环继续}return;
}

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

2 ) 2) 2)后根遍历。若树非空,则按如下规则遍历:
  • 先依次遍历根结点的每棵子树,遍历子树是仍遵循先子树后根的规则。
  • 再访问根结点。
void PostOrder(CSTree T) {//后根遍历if (T != NULL) {CSTree C = T->firstchild;do {PostOrder(C);//对以C为根的子树后根遍历C = C->nextsibling;//依次访问C的右兄弟结点} while (C != NULL);Visit(T);//最后访问根结点}return;
}

其遍历序列与这棵树对应二叉树的中序序列相同。
例如,前文中图 5.23 5.23 5.23中的树,先根遍历序列为 A B E F C D G ABEFCDG ABEFCDG,后根遍历序列为 E F B C G D A EFBCGDA EFBCGDA

3)层次遍历

基本思想与二叉树的层次遍历相同。首先构造辅助队列;根结点入队;队头元素出队,访问当前结点,再将该结点的所有孩子结点入队;依次类推,直到队列为空。

2. 森林的遍历

由于森林和树相互递归的定义,可以得到森林的两种遍历方法:

1 ) 1) 1)先序遍历森林。若森林非空,则按如下规则遍历:
  • 先访问森林中第一棵树的根结点。
  • 先序遍历第一棵树中根结点的子树森林。
  • 先序遍历除去第一棵树之后剩余的树构成的森林。

其实就是按顺序对森林里每棵树依次进行先根遍历,然后把遍历序列按顺序连起来;或者把森林转换成二叉树再进行先序遍历。

2 ) 2) 2)中序遍历森林。若森林非空,则按如下规则遍历:
  • 中序遍历第一棵树中根结点的子树森林。
  • 访问森林中第一棵树的根结点。
  • 中序遍历除去第一棵树之后剩余的树构成的森林。

其实就是按顺序对森林里每棵树依次进行后根遍历,然后把遍历序列按顺序连起来;或者把森林转换成二叉树再进行中序遍历。


对树的遍历,层次遍历又被称为广度优先遍历,先根、后跟又被称为深度优先遍历。
408考研初试中,需掌握手推树与森林的遍历序列的能力,如果运气太差碰到代码实现题,可以先转换成二叉树,再用熟悉的方法处理问题。
以上。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/320247.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JetPack之ViewModel+LiveData

目录 一、概述二、LiveData 使用2.1 创建 LiveData 对象2.2 观察 LiveData 对象2.3 更新 LiveData 对象 三、编写 LiveData Demo3.1 不使用 LiveData3.2 使用 MutableLiveData3.3 使用 MediatorLiveData3.3.1 监听 2 个数据源的变化3.3.2 编写模拟 2 个数据源更新的代码 四、Vi…

java中如何判断一个数是不是素数(质数)

相关概念 质数就是大于1的自然数字中&#xff0c;只能被1和它自己整除的数。 题目 求101~200之间的质素的个数 代码实现 判断一个数是不是质数 for (int j 2; j < i; j) {if(i % j 0){flag false;break;}}if(flag){System.out.println("当前数字是质数");…

Unity 性能优化之遮挡剔除(Occlusion Culling)(六)

提示&#xff1a;仅供参考&#xff0c;有误之处&#xff0c;麻烦大佬指出&#xff0c;不胜感激&#xff01; 文章目录 前言一、遮挡剔除是什么&#xff1f;二、静态遮挡剔除的使用步骤1.标记为遮挡剔除对象2.创建Occlusion Area组件3.烘焙4.Occlusion窗口Bake的参数Smallest Oc…

电子书制作神器,简单操作

​随着数字化时代的到来&#xff0c;电子书籍越来越受到人们的喜爱。而一款优秀的电子翻页书制作软件&#xff0c;则能够帮助你轻松制作出专业级的电子书&#xff0c;让你的阅读体验更加丰富多彩。 今天&#xff0c;我们就来为大家推荐一款优秀的电子翻页书制作软件——FLBOOK在…

全球260多个国家的年通货膨胀率数据集(1960-2021年)

01、数据简介 全球年通货膨胀率是指全球范围内&#xff0c;在一年时间内&#xff0c;物价普遍上涨的比率。这种上涨可能是由于货币过度供应、需求过热、成本上升等原因导致的。通货膨胀率是衡量一个国家或地区经济状况和物价水平的重要指标&#xff0c;通常以消费者价格指数&a…

Flutter笔记:Widgets Easier组件库(12)使用消息吐丝(Notify Toasts)

Flutter笔记 Widgets Easier组件库&#xff08;12&#xff09;使用消息吐丝&#xff08;Notify Toasts&#xff09; - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 29114848416…

如何全面规避医疗数据安全风险?“一中心三大管控域”打开新思路!

作为医院的核心基础设施&#xff0c;数据库已然演变成了一种具有“资产”属性的重要元素。而随着不断变化的医疗业务场景和日趋严格的合规性要求&#xff0c;如何让安全全方位贯穿医疗数据的生命周期&#xff0c;是一项系统性的建设工作&#xff0c;难点诸多。 基于多年的数据…

Vue前端环境准备

vue-cli Vue-cli是Vue官方提供的脚手架&#xff0c;用于快速生成一个Vue项目模板 提供功能&#xff1a; 统一的目录结构 本地调试 热部署 单元测试 集成打包上线 依赖环境&#xff1a;NodeJs 安装NodeJs与Vue-Cli 1、安装nodejs&#xff08;已经安装就不用了&#xff09; node-…

Linux字符设备驱动(二) - 与设备驱动模型的关系

一&#xff0c;从/dev目录说起 从事Linux嵌入式驱动开发的人&#xff0c;都很熟悉下面的一些基础知识&#xff0c; 比如&#xff0c;对于一个char类型的设备&#xff0c;我想对其进行read wirte 和ioctl操作&#xff0c;那么&#xff1a; 1&#xff09;我们通常会在内核驱动中…

tomcat-以服务的方式重启tomcat

背景 双击tomcat的bin目录下面的startup.bat&#xff0c;会留下一个cmd的窗口&#xff0c;很不优雅 使用service服务的方式启动&#xff0c;并且设置为自动启动 找到tomcat的bin目录输入cmd&#xff0c;按Enter&#xff0c;进入命令行界面。执行“service.bat install” 。&…

文件删了,回收站清空了怎么恢复?文件恢复软件一览

在日常生活和工作中&#xff0c;我们常常会遇到误删除文件的情况&#xff0c;有时甚至会因为清空了回收站而无法找回这些文件。这些文件可能包含重要的工作数据、个人照片或其他珍贵的回忆。那么&#xff0c;在这种情况下&#xff0c;我们该如何恢复这些被删除且清空回收站的文…

【项目分享】用 Python 写一个桌面倒计日程序!

事情是这样的&#xff0c;我们班主任想委托我做一个程序&#xff0c;能显示还有几天考试。我立即理解了这个意思&#xff0c;接下了这个项目。 话不多说&#xff0c;来看看这个项目吧—— 项目简介 仓库地址&#xff1a;https://gitee.com/yaoqx/desktop-countdown-day 这是 …

为何美国多IP服务器搭建蜘蛛池SEO更经济?

为何美国多IP服务器搭建蜘蛛池SEO更经济? 随着网络时代的不断演进&#xff0c;搜索引擎优化(SEO)已经成为企业和个人提升网站曝光度的必经之路。在这个过程中&#xff0c;蜘蛛池(Spider Pool)服务被广泛应用。但是有趣的是&#xff0c;美国多IP服务器搭建蜘蛛池SEO服务却相对…

计算机网络-ICMPv6基础概念

前面我们学习了IPv6的基础概念以及IPv6地址的格式与分类&#xff0c;在IPv4中我们通过ARP、广播、ICMP进行地址冲突检测、网络连通性&#xff0c;但是在IPv6中是没有广播和ARP的&#xff0c;都是通过ICMPv6来实现其功能&#xff0c;所以这里我们需要了解下ICMPv6。 一、ICMP协议…

一个基于ComfuUI Api的 AIGC自动绘画实现方案

工作流程图 基本原理已经弄通&#xff0c;下一步要开始编码搬砖了。整个自动绘画的流程如下&#xff0c;暂就不整高深U什么L了&#xff0c;写个简单明了能容易看懂的流程图。UI借用了下墨刀里的AI绘画公开原型 部署节点 整个系统的后端服务典型部署需要3类节点 Aigc Server&…

mac/windows下安装docker,minikube

1、安装docker Get Started | Docker 下载安装docker 就行 启动后&#xff0c;就可以正常操作docker了 使用docker -v 验证是否成功就行 2、安装minikube&#xff0c;是基于docker-desktop的 2.1、点击设置 2.2、选中安装&#xff0c;这个可能需要一点时间 这样安装后&…

【研发管理】产品经理知识体系-组合管理

导读&#xff1a;新产品开发的组合管理是一个重要的过程&#xff0c;它涉及到对一系列新产品开发项目进行策略性选择、优先级排序、资源分配和监控。这个过程旨在确保企业能够最大化地利用有限的资源&#xff0c;以实现其战略目标。 目录 1、组合管理、五大目标 2、组合管理的…

OpenCV的周期性噪声去除滤波器(70)

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇:OpenCV如何通过梯度结构张量进行各向异性图像分割(69) 下一篇 :OpenCV如何为我们的应用程序添加跟踪栏(71) 目录 目标 理论 如何消除傅里叶域中的周期性噪声&#xff1f; 源代码 解释 结果 目…

详解基于 RAG 的 txt2sql 全过程

前文 本文使用通义千问大模型和 ChromaDB 向量数据库来实现一个完整的 text2sql 的项目&#xff0c;并基于实际的业务进行效果的展示。 准备 在进行项目之前需要准备下面主要的内容&#xff1a; python 环境通义千问 qwen-max 模型的 api-keyChromaDB 向量数据库acge_text_…

Sharding Capital: 为什么投资全链流动性基础设施 Entangle ?

写在前面&#xff1a;Entangle 项目的名称取自于量子纠缠(Quantum entanglement)&#xff0c;体现了项目对于构建连接、关联和互通的愿景。就像量子纠缠将不同的粒子联系在一起&#xff0c;Entangle 旨在通过其跨链流动性和合成衍生品的解决方案将不同的区块链网络连接在一起&a…