备战蓝桥杯:树的存储与遍历(dfs和bfs)

树的概念

树的逻辑结构是树形结构,和我们之前的线性结构又不太一样了,是一种一对多的关系

树的结点分为根节点,叶子结点(没有分支的结点) 以及分支结点

从上往下看,每个结点都有0个或多个后继

从下往上看,每个结点除了根结点以外都有一个前驱结点

所以每个结点都有一条边去连接前驱结点,而根结点没有边连接前驱结点,所以结点数=边数+1(除了根结点每个结点都有一条边连接前驱结点,再加上根结点就是结点的个数)

如图,从下往上看,除了根结点,每个结点都有一个前驱结点,也就是对应一条边。所以结点数=边数(9)+1 = 10

关于树的一些相关术语

父结点:直接前驱,根结点没有父结点

孩子结点:直接后继,叶子结点没有直接后继

结点的度:该结点孩子的个数,比如上图A结点的度就是3

树的度:所有结点的度的最大值

树的高度:一共有多少层,图中有四层

两个结点之间的路径:两个结点之间的最短路径

路径长度:两点的路径中,边的个数

有序树:结点的子树顺序按从左到右有序,不能随意更改

无序树:结点的子树顺序是无序的,随便变,没事儿

我们竞赛一般用的都是无序树

有根树:根是固定的

无根树:根是不固定的

(无根树会导致父子关系不明确,我们要把所有清空都存储起来,比如假如a和b之间存在一条边,那我们既要把a存在b的孩子里,也要把b存在a的孩子里)

我们竞赛中用的都是无根树

树的存储

关于树的存储方式有很多,我们本篇文章只学孩子表示法,未来我们的并查集里会学到双亲表示法,竞赛里,我们只需要掌握这两种表示方法就ok了

孩子表示法:对于每个结点,把他所有的孩子全部存起来

因为我们竞赛都是无根树,我们需要把所有情况都考虑到

用vector数组实现孩子表示法

我们竞赛里,一般都是这样给信息

我们首先要创建一个大小充足 的vector的数组,把每个结点的孩子都各自存储在各自的vector里面

如图,我们九个结点,我们就创建一个大小为10的vector数组,下标为0的vector数组我们不用

#include <iostream>
#include <vector>
using namespace std;
const int N = 1e5 + 10;
vector <int> v1[N];
int main()
{int n;cin >> n;}

比如我们看第一个输入的是3和1,那么3和1之间有一条边,我们竞赛都是无根树,所以我们把3当成1的孩子存一次,把1当成3的孩子存一次

1的孩子结点:2,3,4

2的孩子结点:1,5,6

3的孩子结点:1

4的孩子结点:1,7,8,9

5的孩子结点:2

6的孩子结点:2

7,8,9的孩子结点:4

存储时候的代码

#include <iostream>
#include <vector>
using namespace std;
const int N = 1e5 + 10;
vector <int> v1[N];
int main()
{int n;cin >> n;for (int i = 1; i < n; i++){int x, y; cin >> x >> y;v1[x].push_back(y);v1[y].push_back(x);}}

用链式前向星实现孩子表示法

链式前向星就是用链表来存储所有的孩子

我们需要创建一个数组来存储每个结点的一个哨兵位,

然后创建一个哨兵位数组2倍的数组来存储完成e[2*N]和ne[2*N]的数组,还要有id表示存储位置(这里是两倍,因为我们有的结点可能不止一个边,那么就有可能存储两次)

我们实现的时候就是用头插来实现的

比如这个图,我们3和1有一条边,那我们就要把3的哨兵位连接一个1,把1结点的哨兵位连接一个3,代码也就是:id++,e[id] = 1,ne[id]=h[3] h[3] = id,这是把1连接到3的哨兵位,3连接1同理,我们暂且不实现,3和4有一条边,我们把4连接到3的哨兵位的后面,同样是采取头插,id++,e[id]=4,ne[id]=h[3],h[3]=id,这样我们的3结点哨兵位就变成了 头->4->1了,也就是3的两个孩子

实现完整代码如下

#include <iostream>
#include <vector>
using namespace std;
const int N = 1e5 + 10;
int h[N], e[2 * N], ne[2 * N], id;
void add(int x, int y)
{id++;e[id] = x;ne[id] = h[y];h[y] = id;
}
int main()
{int n;cin >> n;for (int i = 1; i < n; i++){int x, y; cin >> x >> y;add(x, y); add(y, x);}
}

树的遍历(DFS和BFS)

DFS,即深度优先遍历,英文叫做Depth First Search

是一种遍历树或者图的一种算法,所谓深度优先遍历,就是每次都尝试往更深的结点走

也就是一条路走到黑

从根结点开始,遍历根结点的孩子,然后再以这个孩子为根遍历它的孩子,所以我们可以写成一种递归的形式

vector存储的树进行dfs

#include <iostream>
#include <vector>
using namespace std;
const int N = 1e6 + 10;
vector <int> edges[N];
bool st[N];void dfs(int u)
{cout << u << " ";st[u] = true;for (auto v : edges[u]){if (!st[v])dfs(v);}
}
int main()
{int n;cin >> n;//建树for (int i = 1; i < n; i++){int a, b; cin >> a >> b;edges[a].push_back(b);edges[b].push_back(a);}//深度优先搜索dfs(1);return 0;
}

过程就是不断的遍历根结点的孩子,不断的遍历根结点的孩子,我们来画一下递归过程图

递归的展开图就是一棵树,递归就是对树进行深度搜索

为了更好的理解递归,我们再画一下斐波那契数列的递归展开图

可以看到,斐波那契算法的递归图画出来也是一棵树

链式前向星存储的树进行dfs

#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int h[N], e[2*N], ne[2*N], id;
bool st[N];
void add(int a, int b)
{id++;e[id] = b;ne[id] = h[a];h[a] = id;
}
void dfs(int u)
{cout << u << " ";st[u] = true;for (int v = h[u]; v; v = ne[v]){if (!st[e[v]]){dfs(e[v]);}}
}
int main()
{int n;cin >> n;for (int i = 1; i < n; i++){int a, b; cin >> a >> b;add(a, b); add(b, a);}dfs(1);return 0;
}

vector存储的树进行bfs

bfs的话,我们的思路就是用队列,我们先把根结点入队列,然后出队列的时候要把该结点的孩子入队列,直到队列为空,搜索完毕

比如这个,我们先把1入队列,然后把输出1并把1出队列,把3,5,2入队列,然后把输出3并把3出队列,把3的孩子7,10带进去,

出5,把4带进去,出2把11带进去,这时候我们的队列里就是7,10,4,11了 我们输出了1,3,5,2 接下来也是这种操作,直到队列为空的时候我们遍历完毕

下面实现我们的代码

#include <iostream>
#include <vector>
#include <queue>
using namespace std;
const int N = 1e5 + 10;
queue <int> q;
vector <int> edges[N];
bool st[N];
void bfs()
{q.push(1); while (q.size()){auto t = q.front();cout << t << " ";st[t] = true;q.pop();for (auto e : edges[t]){if (!st[e]){q.push(e);st[e] = true;}}}}
int main()
{int n;cin >> n;for (int i = 1; i < n; i++){int a, b; cin >> a >> b;edges[a].push_back(b);edges[b].push_back(a);}bfs();}

符合我们的树,结束

链式前向星存储的树进行bfs

#include <iostream>
#include <queue>
using namespace std;const int N = 1e5 + 10;
int h[N], ne[2 * N], e[2 * N], id;
bool st[N];
void add(int a,int b)
{id++;e[id] = b;ne[id] = h[a];h[a] = id;
}
queue <int> q;
void bfs()
{q.push(1);while (q.size()){auto t = q.front(); q.pop();cout << t << " ";st[t] = true;for (int i = h[t]; i; i = ne[i]){if (!st[e[i]]){q.push(e[i]);st[e[i]] = true;}}}
}int main()
{int n;cin >> n;for (int i = 1; i < n; i++){int a, b; cin >> a >> b;add(a, b); add(b, a);}bfs();return 0;
}

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

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

相关文章

欧拉公式和傅里叶变换

注&#xff1a;英文引文机翻&#xff0c;未校。 如有内容异常&#xff0c;请看原文。 Euler’s Formula and Fourier Transform Posted byczxttkl October 7, 2018 Euler’s formula states that e i x cos ⁡ x i sin ⁡ x e^{ix} \cos{x} i \sin{x} eixcosxisinx. When…

《零基础Go语言算法实战》【题目 2-22】Go 调度器优先调度问题

《零基础Go语言算法实战》 【题目 2-22】Go 调度器优先调度问题 下面代码的输出是什么&#xff1f;请说明原因。 package main import ( "fmt" "runtime" "sync" ) func main() { runtime.GOMAXPROCS(1) wg : sync.WaitGroup{} wg.Add(10)…

解读若依微服务架构图:架构总览、核心模块解析、消息与任务处理、数据存储与缓存、监控与日志

文章目录 1. 引言2. 架构总览3. 核心模块解析3.1 服务注册与配置中心Nacos&#xff1a;微服务的中枢 3.2 网关层ruoyi-gateway&#xff1a;服务的统一入口 3.3 核心业务服务3.4 认证服务ruoyi-auth&#xff1a;认证与授权的守护者 3.5 异构服务整合Sidecar&#xff1a;连接异构…

Rank-Analysis——LOL 排位战绩查询分析器

项目地址&#xff1a; https://github.com/wnzzer/lol-rank-record-analysis 项目采用 Golang electron lol 战绩查询&#xff0c;一键查询你的混子队友&#xff01; 很早以前就想做这个&#xff0c;最近学了学前端的内容&#xff0c;就拿这个练练手&#xff0c;后端也是新学…

el-table自定义按钮控制扩展expand

需求&#xff1a;自定义按钮实现表格扩展内容的展开和收起&#xff0c;实现如下&#xff1a; 将type“expand”的表格列的宽度设置为width"1"&#xff0c;让该操作列不展示出来&#xff0c;然后通过ref动态调用组件的内部方法toggleRowExpansion(row, row.expanded)控…

FFmpeg入门

在音视频处理领域&#xff0c;有一款神器级的工具横扫开发者圈&#xff0c;那就是 FFmpeg。它被誉为“音视频处理的瑞士军刀”&#xff0c;凭借强大的功能和开源的特性成为众多开发者和媒体从业者的首选。今天&#xff0c;我们就来聊聊 FFmpeg 的入门使用&#xff0c;带你轻松开…

计算机网络 网络层 2

IP协议&#xff1a; Ip数据报的格式&#xff1a; 首部:分为固定部分 和 可变部分 固定部分是20B 版本&#xff1a;表明了是IPV4还是IPV6 首部长度&#xff1a;单位是 4B&#xff0c;表示的范围是&#xff08;5~15&#xff09;*4B 填充&#xff1a;全0&#xff0c;,让首部变…

【Java计算机毕业设计】基于SSM旅游景区网络购票系统【源代码+数据库+LW文档+开题报告+答辩稿+部署教程+代码讲解】

源代码数据库LW文档&#xff08;1万字以上&#xff09;开题报告答辩稿 部署教程代码讲解代码时间修改教程 一、开发工具、运行环境、开发技术 开发工具 1、操作系统&#xff1a;Window操作系统 2、开发工具&#xff1a;IntelliJ IDEA或者Eclipse 3、数据库存储&#xff1a…

后端技术选型 sa-token校验学习 中 文档学习

目录 依赖 配置文件 登录验证 登录与注销 Cookie 自动注入 前后端分离(无 Cookie 模式) 何为 Cookie 何为无 Cookie 模式? 解决方案 1、后端将 token 返回到前端 2、前端将 token 提交到后端 其它解决方案&#xff1f; 自定义 Token 前缀 [ 记住我 ] 模式 前后端…

量子计算:从薛定谔的猫到你的生活

文章背景 说到量子计算&#xff0c;不少人觉得它神秘又遥不可及。其实&#xff0c;它只是量子物理学的一个“应用小分支”。它的核心在于量子比特的“叠加”和“纠缠”&#xff0c;这些听上去像科幻小说的概念&#xff0c;却为计算世界开辟了一片全新的天地。如果经典计算是“…

TPS61022 PFM的机制以及TPS61xxx转换器的PFM与PWM之间的负载阈值

引言 TI 的大多数 TPS61xxx 低压升压转换器都配备了 PSM&#xff08;省电模式&#xff09;&#xff0c;以帮助提高轻负载效率。但是&#xff0c;当它处于重负载状态时&#xff0c;输出纹波通常会高于 PWM。此外&#xff0c;PSM 和 PWM 之间的负载电流阈值不会直观地写入数据表中…

vue使用自动化导入api插件unplugin-auto-import,避免频繁手动导入

‌unplugin-auto-import‌是一个现代的自动导入插件&#xff0c;旨在简化前端开发中的导入过程&#xff0c;减少手动导入的繁琐工作&#xff0c;提升开发效率。它支持多种构建工具&#xff0c;包括Vite、Webpack、Rollup和esbuild&#xff0c;并且可以与TypeScript配合使用&…

电力场景红外测温图像均压环下的避雷器识别分割数据集labelme格式2436张1类别

数据集格式&#xff1a;labelme格式(不包含mask文件&#xff0c;仅仅包含jpg图片和对应的json文件) 图片数量(jpg文件个数)&#xff1a;2436 标注数量(json文件个数)&#xff1a;2436 标注类别数&#xff1a;1 标注类别名称:["arrester"] 每个类别标注的框数&am…

利用 NATIVE SQL 实现不区分供应商名字大小写进行模糊查询

公司有个需求 &#xff0c;当按用英文名字来进行查询时&#xff0c;可以实现不区分供应商名字大小写进行模糊查询。 例如&#xff1a;如果用户输入‘br’ 那么可以查出名字含有 ‘BR’、‘bR’、‘Br’ 、‘br’ 的供应商来。利用SAP 常规的 Open SQL 是实现不了的。 只能利用…

lobechat搭建本地知识库

本文中&#xff0c;我们提供了完全基于开源自建服务的 Docker Compose 配置&#xff0c;你可以直接使用这份配置文件来启动 LobeChat 数据库版本&#xff0c;也可以对之进行修改以适应你的需求。 我们默认使用 MinIO 作为本地 S3 对象存储服务&#xff0c;使用 Casdoor 作为本…

隐私计算,构建安全的未来数据空间

大数据产业创新服务媒体 ——聚焦数据 改变商业 在医疗领域&#xff0c;不同医院之间需要共享患者数据&#xff0c;以提供更全面准确的诊断和治疗方案。 传统的数据处理方式通常是数据经过转换隐藏重要数据后再进行分析&#xff0c;虽然可以保护数据隐私&#xff0c;但在数据源…

基于DFT与IIR-FIR滤波器的音频分析与噪声处理

基于DFT与IIR-FIR滤波器的音频分析与噪声处理 【完整源码文档报告】 【需要可随时联系博主&#xff0c;常在线能秒回!】 系统功能与实现介绍 功能与实现 音频处理系统界面搭建&#xff1a;利用MATLAB的GUI工具&#xff0c;构建了音频分析界面&#xff0c;包括文件导入、录…

分布式ID—雪花算法

背景 现在的服务基本是分布式、微服务形式的&#xff0c;而且大数据量也导致分库分表的产生&#xff0c;对于水平分表就需要保证表中 id 的全局唯一性。 对于 MySQL 而言&#xff0c;一个表中的主键 id 一般使用自增的方式&#xff0c;但是如果进行水平分表之后&#xff0c;多…

Artec Leo 3D扫描仪与Ray助力野生水生动物法医鉴定【沪敖3D】

挑战&#xff1a;捕获大型水生哺乳动物&#xff08;如鲸鱼&#xff09;的数据&#xff0c;搭建全彩3D模型&#xff0c;用于水生野生动物的法医鉴定、研究和保护工作。 解决方案&#xff1a;Artec Eva、Artec Space Spider、Artec Leo、Artec Ray、Artec Studio、CT scans 效果&…

Realsense相机驱动安装及其ROS通讯配置——机器人抓取系统系列文章(四)

文章目录 概要1 Realsense相机驱动安装Method1: 使用Intel服务器预编译包Method2: 使用ROS服务器预编译包Method3: 使用SDK源代码方法对比总结 2 Realsense-ROS通讯配置与使用2.1 Realsense-ROS包安装2.2 ROS节点启动 小结Reference 概要 本文首先阐述了Realsense相机驱动安装…