树和森林(快来瞧)

news2024/9/22 9:46:27

森林的定义 

森林是由多颗互不相交的树所构成的树的集合,即森林包含多棵树,每一棵树都有自己的根结点。一棵树也可以看成森林。

树的表示及基本操作 

1.树(一般树)的表示方法

1.1树的双亲表示法

树的双亲表示法是将树的各个节点存储在一个数组中,每一个结点都与数组的下标唯一对应,在每个结点中记录其父结点的下标,根结点的父结点为-1。

(最左孩子结点:一个结点的孩子结点中位于最左边的孩子结点)

在实际应用中,树的双亲表示法可以简单地直接用两个数组data和pa表示,但需要指明结点的数量和根结点的下标。

注意:在树的双亲表示法中必须严格按照层次遍历的顺序进行编号。

#include<iostream>
using namespace std;
constexpr auto N = 30;
typedef char datatype;
struct paNode {
	int pa; //父结点的下标
	datatype data;
	paNode() :pa(-1) {};
};
typedef struct {
	paNode tree[N];
	int n;	//树中节点的数量
	int root;  //树的根结点下标
}paTree;

//双亲表示法的树的创建
paTree create_paTree(datatype data[N], int pa[N], int n) {
	paTree t;
	t.n = n;
	for (int i = 0; i < n; i++) {
		t.tree[i].pa = pa[i], t.tree[i].data = data[i];
		if (pa[i] == -1)
			t.root = i;
	}
}

//求双亲表示法的树中某个结点的最左孩子结点和右兄弟节点
//求树t中结点cur的最左孩子结点,结果作为返回值。如果cur为叶结点,则返回-1
int lm_child(paTree t, int cur) {
	for(int i = cur + 1; i < t.n; i++) {
		if (t.tree[i].pa == cur)
			return i; //cur的最左孩子结点为i
	}
	return -1;
}

//求树t中结点cur的右兄弟结点,结果作为返回值。如果cur没有右兄弟结点,则返回-1
int r_brother(paTree t, int cur) {
	if (cur < t.n && t.tree[cur + 1].pa == t.tree[cur].pa) {
		return cur + 1;
	}
	return -1;
}

int main() {

}

1.2树的左右链表示法

树的左右链表示法是指在树的每个结点中记录该结点的最左孩子结点和其右兄弟结点。这种表示方法中每个结点中应该包含节点的数据、结点的父节点、结点的最左孩子结点和结点的右兄弟节点。可以用链表表示,也可以用数组表示。

#include<iostream>
using namespace std;
constexpr auto N = 30;
typedef char datatype;

struct lrbNode {
	datatype data;
	int pa;
	int lmc; //最左孩子结点
	int rb; //右兄弟结点
	lrbNode() :lmc(-1), rb(-1) {};
};
typedef struct {
	lrbNode tree[N]; //结点表
	int n; //树的节点总数
	int root;//树的根结点下标
}lrbTree;

//树的孩子列表数组表示法的基本操作
//创建数,data为树的各结点的数据,pa为各结点的父节点,n为树的结点数
lrbTree create_lrbTree(datatype data[], int pa[], int n) {
	lrbTree t;
	t.n = n;
	for (int i = 0; i < n; i++) {
		t.tree[i].data = data[i];
		if (pa[i] == -1) t.root = i; //指定树的父节点
		else {
			t.tree[i].pa = pa[i];//指定结点i的父节点
			if (t.tree[pa[i]].lmc == -1)t.tree[pa[i]].lmc = i; //i为其父节点的第一个孩子结点
			else {
				t.tree[i - 1].rb = i; //i有左兄弟结点i-1,i即为i-1的右兄弟节点
			}
		}
	}
	return t;
}

//求树t中结点cur的最左孩子结点的下标,结果作为返回值
int lm_child(lrbTree t,int cur) {
	return t.tree[cur].lmc;
}

//求树t中结点cur的右兄弟的下标,结果作为函数返回值
int r_brother(lrbTree t, int cur) {
	return t.tree[cur].rb;
}

int main() {

}

树和森林的遍历

树的遍历 

#include<iostream>
using namespace std;
constexpr auto N = 30;
typedef char datatype;

struct lrbNode {
	datatype data;
	int pa;
	int lmc; //最左孩子结点
	int rb; //右兄弟结点
	lrbNode() :lmc(-1), rb(-1) {};
};
typedef struct {
	lrbNode tree[N]; //结点表
	int n; //树的节点总数
	int root;//树的根结点下标
}lrbTree;

//树的孩子列表数组表示法的基本操作
//创建数,data为树的各结点的数据,pa为各结点的父节点,n为树的结点数
lrbTree create_lrbTree(datatype data[], int pa[], int n) {
	lrbTree t;
	t.n = n;
	for (int i = 0; i < n; i++) {
		t.tree[i].data = data[i];
		if (pa[i] == -1) t.root = i; //指定树的父节点
		else {
			t.tree[i].pa = pa[i];//指定结点i的父节点
			if (t.tree[pa[i]].lmc == -1)t.tree[pa[i]].lmc = i; //i为其父节点的第一个孩子结点
			else {
				t.tree[i - 1].rb = i; //i有左兄弟结点i-1,i即为i-1的右兄弟节点
			}
		}
	}
	return t;
}

//求树t中结点cur的最左孩子结点的下标,结果作为返回值
int lm_child(lrbTree t, int cur) {
	return t.tree[cur].lmc;
}

//求树t中结点cur的右兄弟的下标,结果作为函数返回值
int r_brother(lrbTree t, int cur) {
	return t.tree[cur].rb;
}

//树的三种遍历方法
//对树t进行先根遍历,rt为当前子树的根结点
void preOrder(lrbTree t, int rt) {
	if (rt == -1)return;
	cout << t.tree[rt].data; //先访问根结点
	int cur = lm_child(t, rt); //根结点的最左孩子结点
	while (cur != -1) { //从树t的最左子树开始,依次先根遍历t的子树森林
		preOrder(t, cur);
		cur = r_brother(t, cur); //结点cur的右兄弟结点
	}
}

//对树t进行中根遍历,rt为当前子树的根结点
void midOrder(lrbTree t, int rt) {
	if (rt == -1)return;
	int cur = lm_child(t, rt); //根结点的最左孩子结点
	midOrder(t, cur);//中根遍历t的最左子树
	cout << t.tree[rt].data; //在t的最左子树遍历结束后访问根结点
	while (cur != -1) { //根结点的最左孩子结点
		cur = r_brother(t, cur);//结点cur的右兄弟结点
		midOrder(t, cur);
	}
}

//对树t进行后根遍历,rt为当前子树的根结点
void postOrder(lrbTree t, int rt) {
	if (rt == -1) return;
	int cur = lm_child(t, rt);  //根结点的最左孩子结点
	while (cur != -1) { //从t的最左孩子结点出发,依次后根遍历t的子树森林
		postOrder(t, cur);
		cur = r_brother(t, cur);  //结点cur的右兄弟结点
	}
	cout << t.tree[rt].data; //最终访问根结点
}

int main() {

}

树的括号表示法

【待补充】

森林的遍历【无代码演示】

森林有多颗树构成,每一棵树有一个根结点,可以定义一个辅助结点,森林中每颗子树的根结点作为其孩子结点,这样森林就变味一棵树,因此对森林的遍历可以转化为对树的遍历。

森林有如下两种遍历方法:
        先根遍历森林:从左到右依次先根遍历森林的各个子树。
        后根遍历森林:从左到右依次后根遍历森林的各个子树。

森林与二叉树的转换

森林树转换成二叉树后,对森林的操作都可以转换成对相应二叉树的操作。

森林转换成二叉树

 

参考:

二叉树与树、森林之间的转换_kindoms214的博客-CSDN博客_将二叉树转换成对应的树或森林https://blog.csdn.net/kindoms214/article/details/85699598?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522167422309216800211583404%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=167422309216800211583404&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-85699598-null-null.142%5Ev71%5Econtrol_1,201%5Ev4%5Eadd_ask&utm_term=%E4%BA%8C%E5%8F%89%E6%A0%91%E4%B8%8E%E6%A3%AE%E6%9E%97%E7%9A%84%E8%BD%AC%E6%8D%A2&spm=1018.2226.3001.4187

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

现场工程师出手-PCAPHub与云SSH隧道稳妥实现异地LAN工业联测

在去年&#xff0c;因为众所周知的因素影响&#xff0c;项目的甲方主动提出延缓设备的交付。作为乙方&#xff0c;尽管项目延缓是甲方提出的&#xff0c;但依旧希望按期交付&#xff0c;这样才能回款&#xff0c;熬过一年。其实&#xff0c;2022年初&#xff0c;几类传感器、压…

S7-1200PLC与ABB机器人进行PROFINET通信的具体方法和步骤详解

S7-1200PLC与ABB机器人进行PROFINET通信的具体方法和步骤详解 1. TIA博途一侧的配置: 当我们安装好RobotStudio软件后,可以在以下的目录中C:\ProgramData\ABB Industrial IT\Robotics IT\DistributionPackages\ABB.RobotWare-6.08.0134\RobotPackages\RobotWare_RPK_6.08.013…

【JavaWeb】JavaScript基础语法(上)

✨哈喽&#xff0c;进来的小伙伴们&#xff0c;你们好耶&#xff01;✨ &#x1f6f0;️&#x1f6f0;️系列专栏:【JavaWeb】 ✈️✈️本篇内容:JavaScript基础语法(上)&#xff01; &#x1f680;&#x1f680;代码托管平台github&#xff1a;JavaWeb代码存放仓库&#xff01…

ESP32设备驱动-TSL2561亮度传感器驱动

TSL2561亮度传感器驱动 1、TSL2561介绍 TSL2560 和 TSL2561 是第二代环境光传感器器件。每个都包含两个集成模数转换器 (ADC),用于集成来自两个光电二极管的电流。两个通道的整合同时发生。转换周期完成后,转换结果分别传送到通道 0 和通道 1 数据寄存器。传输是双缓冲的,…

【头歌】单链表的基本操作

单链表的基本操作第1关&#xff1a;单链表的插入操作任务描述本关任务&#xff1a;编写单链表的初始化、插入、遍历三个操作函数。相关知识链表是线性表的链式存储结构的别称&#xff0c;特点是以“指针”指示后继元素&#xff0c;因此线性表的元素可以存储在存储器中任意一组存…

Linux常用命令——speedtest-cli命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) speedtest-cli 命令行下测试服务器外网速度 补充说明 speedtest-cli是一个使用python编写的命令行脚本&#xff0c;通过调用speedtest.net测试上下行的接口来完成速度测试&#xff0c;最后我会测试运维生存时间…

YOLOV3 Pytorch版本代码解读

YOLOV3 Pytorch版本代码解读 代码与coco数据集关注wx公众号JokerTong回复yolov3即可获取 参考视频 YOLO系列算法 文章目录YOLOV3 Pytorch版本代码解读数据集准备与关键文件说明前提准备代码大致流程需要自行修改代码的部分项目代码解读一 数据与标签的读取二 模型构造convoluti…

数据库工具类的编写

package com.bjpowernode.jdbc.utils;import java.sql.*; import java.util.ResourceBundle;/*** 数据库工具类简化JDBC的代码编写。** 在同一个没有结束的程序中&#xff0c;DBUtil类只加载一次&#xff0c;加载一次以后&#xff0c;再次调用该类中的方法&#xff0c;本不会再…

基于Echarts构建大数据招聘岗位数据可视化大屏

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

SpringBoot 3.0.x使用SpringDoc

为什么使用SpringDoc 在Springfox3.0停更的两年里&#xff0c;SpringBoot进入3.0时代&#xff0c; SpringFox出现越来越多的问题&#xff0c;最为明显的就是解析器的问题&#xff0c;已经在上文 中解释清楚&#xff0c;这里就不再赘述。 SpringDoc是Spring官方推荐的API&#x…

Spring笔记上(基于注解开发)

一、第三方资源配置管理 以DataSource连接池对象为例&#xff0c;进行第三方资源配置管理。 1. 管理DataSource连接池对象 spring整合Druid、C3P0数据库连接池 1.1 管理Druid连接池 1、准备数据 create database if not exists spring_db character set utf8; use spring_db; …

二、python基础语法篇(黑马程序猿-python学习记录)

黑马程序猿的python学习视频&#xff1a;https://www.bilibili.com/video/BV1qW4y1a7fU/ 目录 一 、print 1. end 2. \t对齐 二、字面量 1. 字面量的含义 2. 常见的字面量类型 3. 如何基于print语句完成各类字面量的输出 三、 注释的分类 1. 单行注释 2. 多行注释 3. 注释的…

MXNet的Faster R-CNN(基于区域提议网络的实时目标检测)《9》

MXNet的Faster R-CNN(基于区域提议网络的实时目标检测)《1》&#xff1a;论文源地址&#xff0c;克隆MXNet版本的源码&#xff0c;安装环境与测试&#xff0c;以及对下载的源码的每个目录做什么用的&#xff0c;做个解释。 MXNet的Faster R-CNN(基于区域提议网络的实时目标检测…

【手写 Vue2.x 源码】第四十一篇 - 组件部分 - 生成组件的真实节点

一&#xff0c;前言 上篇&#xff0c;介绍了组件部分-组件的生命周期&#xff0c;主要涉及以下几部分&#xff1a; 本篇&#xff0c;组件部分-生成组件的真实节点&#xff1b; 二&#xff0c;生成组件的真实节点 1&#xff0c;前文回顾 前篇&#xff0c;在 createElement 方…

【剧前爆米花--爪哇岛寻宝】Java中有关异常类的详细讲解

作者&#xff1a;困了电视剧 专栏&#xff1a;《JavaSE语法与底层详解》 文章分布&#xff1a;这是一篇关于Java中异常类的文章&#xff0c;在本篇文章中详细讲解了异常的使用逻辑和底层的执行过程&#xff0c;如有疏漏&#xff0c;欢迎大佬指正&#xff01; 目录 异常的体系结…

<C++>哈希

文章目录1. unordered系列容器1.1 unordered_map1.1.1 unordered_map的文档介绍1.1.2 unordered_map的接口说明1.2 unordered_set2. 哈希概念3. 哈希冲突4. 哈希函数5. 哈希冲突解决5.1 闭散列5.1.1 线性探测5.1.2 二次探测5.2 开散列5.3 开散列与闭散列比较6. 模拟实现1. unor…

配置野火霸道V2环境

配置野火霸道V2环境野火霸道开发板学习笔记信息说明下载安装Keil5配置Keil以使用DAP下载器DAP下载器的使用使用串口下载程序安装USB转串口驱动CH340检查是否安装成功配置MCUISP软件野火霸道开发板学习笔记 信息说明 日期 : 2023-01-23开发板: 野火霸道V2芯片型号: STM32F103Z…

[Paper Reading] Towards Conversational Recommendation over Multi-Type Dialogs

[Paper Reading] Towards Conversational Recommendation over Multi-Type Dialogs 文章目录[Paper Reading] Towards Conversational Recommendation over Multi-Type Dialogs论文简介快速回顾论文&#xff08;借助scispace&#xff09;梳理一下文章内容&#xff08;参考百度N…

自动化将Gitee的仓库导入Github

自动化将Gitee的仓库导入Github准备工作获取方式gitee的授权码github授权码工具源码用法下载gitee所有仓库到本地下载并更新到github&#xff08;自动创建仓库&#xff09;写在最后本方法能实现自动创建仓库 脚本及用法放在文章最后了&#xff0c;需要的自取 转跳到结尾 准备工…

高性能 Java 框架。Solon v1.12.3 发布(春节前兮的最后更)

一个更现代感的 Java "生态型"应用开发框架&#xff1a;更快、更小、更自由。不是 Spring&#xff0c;没有 Servlet&#xff0c;也无关 JavaEE&#xff1b;新兴独立的开放生态 &#xff08;已有150来个生态插件&#xff09; 。主框架仅 0.1 MB。 相对于 Spring Boot…