BFS:解决拓扑排序问题

文章目录

  • 什么是拓扑排序?
  • 关于拓扑排序的题
    • 1.课程表
    • 2.课程表Ⅱ
    • 3.火星词典
  • 总结

在这里插入图片描述

什么是拓扑排序?

要知道什么拓扑排序我们首先要知道什么是有向无环图,有向无环图我们看名字其实就很容易理解,有向就是有方向,无环就是没有环形结构,这里我们展示一下有向无环图和有向有环图:
在这里插入图片描述
可以看见我们改变了一个边的方向,这个图就产生了环,接下来我们来介绍一下有向图中的一些专业术语:
入度(Indegree):一个顶点的入度是指有多少条边指向这个顶点。换句话说,它表示该顶点有多少个直接前驱节点。(简单来说就是对于一个顶点来说,所有指向他的边之和)

出度(Outdegree):一个顶点的出度是指从这个顶点出发有多少条边。也就是说,它表示该顶点有多少个直接后继节点。(简单来说对于一个顶点来说,,这个顶点往外伸出的边的总和)

接下来我们来说说AOV网,也就是顶点活动图。
在图论和调度问题中,AOV(Activity On Vertex)网是一个非常重要的概念。AOV网通常表示一组活动及其之间的依赖关系,特别适用于项目管理、任务调度和依赖分析等领域。在AOV网中,活动被表示为顶点,依赖关系被表示为有向边。这种结构使得我们可以通过拓扑排序等算法来有效地处理和分析活动的先后顺序。

最后我们再来说说拓扑排序,,简单介绍了上面的概念之后,拓扑排序就相当简单了,拓扑排序就是先将入度为零的顶点删除列出来,,并且将入度为0的连接的边删除。
在这里插入图片描述
删除之后,,再将删除了的剩下的图中的入度为零的取出来,但是这里取出来的方法有两种,所以拓扑排序的 结果也不止一种。
在这里插入图片描述
接下来我们就只能取5了,然后就是取4和6。
在这里插入图片描述
这不是唯一的拓扑排序的结果。
接下来我们来坐坐拓扑排序的问题

关于拓扑排序的题

1.课程表

题目链接
题目:

在这里插入图片描述

样例输出和输入:

在这里插入图片描述

这道题的意思很简单,这道题首先给我们numCourse个课程,我们要把给出的课程全部选修完,但是这个课程不是随便选修的,我们不能想选哪门选哪门,后面给出了一个数组,
在这里插入图片描述
这个数组给出了选修课的对应关系,我们要修b这门课程就得先把b这门课程先修完,这么说有点抽象,我们来看个例子。
在这里插入图片描述
根据上面这个例子就可以推出这个关系,这不是直接转换为我们的拓扑排序了吗,这道题本质就是判断这个图有没有环,如果无环就返回true,如果有环就返回false。
算法原理:
上面算法原理基本已经讲完了,我们来看看代码如何书写,顺便再讲一点,这里我们要用拓扑排序问题又来了,我们是不是要建一个图,这里有涉及到该如何建图,这里我们讲一种方法,用邻接表建图,邻接表是什么呢?
在这里插入图片描述
这大致就是邻接表,我们可以用一个顶点去索引这个节点指向的一系列节点,那么邻接表该如何实现呢?
邻接表一般的实现方法有:
1.unordered_map<int,vector<>>
2.vector<vector<>>
第一种实现方法用法很广泛,但是第二种实现方法很局限

代码展示:

class Solution {
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {//准备工作unordered_map<int, vector<int>> edges;//邻接表存储图vector<int> in(numCourses);//用来标记每个顶点的入度//建图for (auto e : prerequisites){//先找到对应关系,b去映射a,是b指向aint a = e[0], b = e[1];//有一个b指向a的一条边edges[b].push_back(a);//在b这个节点后面插入ain[a]++;}//拓扑排序queue<int> q;//将所有入度为零的点添加到队列中for (int i = 0;i < numCourses;i++){//如果当前节点的入度为0,直接入队列if (in[i] == 0){q.push(i);}}//来一次BFSwhile (q.size()){int t = q.front();q.pop();//如果这道题是求最终for (auto e : edges[t]){in[e]--;if (in[e] == 0)q.push(e);}}for (int i = 0;i < numCourses;i++){if (in[i] != 0){return false;}}return true;
}
};

运行结果:
在这里插入图片描述

2.课程表Ⅱ

题目链接
题目:

在这里插入图片描述

样例输出和输入:

在这里插入图片描述

这道题和第一道题几乎一模一样,但是问法上有些许差异,上道题让我们判断,但是这道题让我们返回结果,返回拓扑排序之后的那个数组,我们这里如果能拓扑排序则返回数组,如果不能则返回空的数组。

算法原理:
我们再BFS的时候每次BFS往内部往容器内插入数据即可。
代码展示:

class Solution {
public:vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {unordered_map<int,vector<int>> edges;vector<int> in(numCourses);vector<int> anwser;//先建图for(auto e:prerequisites){int a=e[0],b=e[1];edges[b].push_back(a);in[a]++;}queue<int> q;//拓扑排序for(int i=0;i<numCourses;i++){//如果入度为零则直接返回if(in[i]==0){q.push(i);}}while(q.size()){int t=q.front();q.pop();anwser.push_back(t);for(auto e:edges[t]){in[e]--;if(in[e]==0){q.push(e);}}}for(int i=0;i<numCourses;i++){if(in[i]){return vector<int>();}}return anwser;}
};

运行结果:
在这里插入图片描述

3.火星词典

题目链接
题目:

在这里插入图片描述

样例输出和输入:

在这里插入图片描述

这道题就有点难了,我们首先要搞定题意,首先在我们印象里的字典序就是比如比较abcabf这链各个字符串进行字典序比较,很显然后面的字典序大于前面的字典序,这是地球上的规则,但是上面给出了一个火星上的规则,所以在火星上,字典序可能和地球上不一样,这道题就是让我们求火星上的字典序排序,首先它先给出了一个words单词列表,这个单词列表是已经排好序的每个单词,这道题让我们返回的是给出的每个字符的字典序的大小的排序,从大到小,如果比较不出来就返回空字符串,这里我们给出 一个简单例子:
在这里插入图片描述
OK,搞懂题意了,我们来讲解算法原理

算法原理:

这道题其实也隐藏着拓扑排序,首先我们来看比较,这个比较就存在先后顺序,没有比w大的,所以没有指向w的,有比e大的所有指向e的,我们根据上面的比较关系来建立一个图:
在这里插入图片描述
经过我们每次的比较,我们得到的字母的大小关系建立的图就是上面这个,然后进行拓扑排序:
在这里插入图片描述
代码展示:

class Solution 
{
public:unordered_map<char,unordered_set<char>> edges;//储存图unordered_map<char,int> in;//统计入度bool check;//处理边界情况string alienOrder(vector<string>& words) {//建图+初始化入度hash表int m=words.size();for(auto s:words){for(auto ch:s){in[ch]=0;}}for(int i=0;i<m;i++){for(int j=i+1;j<m;j++){add(words[i],words[j]);if(check==true){return "";}}}queue<char> q;for(auto &[a,b]:in){if(b==0)q.push(a);}string ret;while(q.size()){char t=q.front();q.pop();ret+=t;for(auto e:edges[t]){in[e]--;if(in[e]==0)q.push(e);}}for(auto &[a,b]:in){if(b)return "";}return ret;}void add(string& a,string& b){int n=min(a.size(),b.size());int i=0;for(;i<n;i++){if(a[i]!=b[i]){char s1=a[i],s2=b[i];//a->b;if(!edges.count(s1)||!edges[s1].count(s2)){edges[s1].insert(s2);in[s2]++;}break;}}if(i==b.size()&&i<a.size())check=true;}
};

运行结果:
在这里插入图片描述

总结

在本文中,我们详细探讨了广度优先搜索(BFS)在解决拓扑排序问题中的应用。从拓扑排序的定义和基本概念出发,我们介绍了其在有向无环图(DAG)中的重要性。通过一步步剖析 BFS 算法的实现过程,我们展示了如何利用 BFS 有效地生成拓扑排序,并解决实际中的复杂问题。

在实现拓扑排序的过程中,BFS 提供了一种直观且高效的解决方案。通过维护一个入度数组和一个队列,BFS 能够准确地找到没有前驱节点的顶点,并逐步扩展到整个图。这种方法不仅易于理解和实现,而且在时间复杂度和空间复杂度上都表现优异,能够处理规模较大的图结构。

总结而言,广度优先搜索为拓扑排序提供了一种强大而灵活的工具。在面对各种复杂的依赖关系和任务调度问题时,BFS 的应用不仅能够确保结果的正确性,还能显著提升计算效率。希望通过本文的讲解,读者能够深入理解 BFS 在拓扑排序中的应用原理,并能够在实际编程中灵活运用这一算法,解决各类相关问题。未来,我们可以继续探索其他算法在拓扑排序中的应用,以及如何优化和扩展这些算法,以应对更复杂的实际需求。

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

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

相关文章

028基于SSM+Jsp的电影售票系统

开发语言&#xff1a;Java框架&#xff1a;ssm技术&#xff1a;JSPJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包…

梅雨季要祛湿!分不清寒湿和湿热,小心越祛越湿!4个方法,助你温和排湿热与寒湿

梅雨季又又又又到了&#xff0c;苏州的雨已经连下3天了&#xff0c;到处都湿哒哒、黏糊糊&#xff01;胃口不好、身体酸重、心情不好……湿气太重了&#xff01; 中医有一句话说“湿气在&#xff0c;百病害&#xff0c;湿气除&#xff0c;百病无”&#xff0c;意思是“湿”为万…

编写一个可复用且使用方式简单的部署脚本

只需一行命令就可使用应用部署或重新部署 当我们部署Java项目时&#xff0c;一般有两种部署方式&#xff1a; 使用java -jar命令来运行jar包将应用打成jar包以容器的方式进行部署 本篇文章主要讲解第二种方式&#xff0c;以部署xxl-job-admin为例 1.编写restart.sh脚本&…

IDEA启动项目Error:java: JDK isn‘t specified for module ‘test‘

错误原因&#xff1a; idea自带JDK不匹配导致项目启动失败 解决方法&#xff1a; 修改idea自带JDK为自己安装的JDK 调整步骤&#xff1a;

《编译原理》阅读笔记:p18

《编译原理》学习第 3 天&#xff0c;p18总结&#xff0c;总计 14页。 一、技术总结 1.assembler (1)计算机结构 要想学习汇编的时候更好的理解&#xff0c;要先了解计算机的结构&#xff0c;以下是本人学习汇编时总结的一张图&#xff0c;每当学习汇编时&#xff0c;看到“…

线上OOM问题排查总结

自己搭建了一个小博客&#xff0c;该文章与博客文章同步。 一般情况下&#xff0c;出现OOM主要有一下三种原因。 一次性申请对象的太多。更改申请对象数量。内存资源耗尽未释放。找到未释放的对象进行释放。本身资源不够。jmap -heap 查看堆信息。 分几种情况解决&#xff1…

多模态-大模型:MLLM综述(适用初学)

文章目录 前言一、多模态模型基础知识二、多模态指令调优&#xff08;M-IT&#xff09;1.MLLM基础2.模态对齐3.数据获取4.模态桥接 三、多模态上下文学习&#xff08;M-ICL&#xff09;三、多模态思维链 (M-CoT)四、LLM辅助视觉推理1.训练范式2. LLM功能 五、一些思考总结 前言…

OS中断机制-外部中断触发

中断函数都定义在中断向量表中,外部中断通过中断跳转指令触发中断向量表中的中断服务函数,中断指令可以理解为由某个中断寄存器的状态切换触发的汇编指令,这个汇编指令就是中断跳转指令外部中断通过在初始化的时候使能对应的中断服务函数如何判断外部中断被触发的条件根据Da…

关于ONLYOFFICE8.1版本桌面编辑器测评——AI时代的领跑者

关于作者&#xff1a;个人主页 目录 一.产品介绍 1.关于ONLYOFFICE 2.关于产品的多元化功能 二.关于产品体验方式 1.关于套件的使用网页版登录 2.关于ONLYOFFICE本地版 三.关于产品界面设计 四.关于产品文字处理器&#xff08;Document Editor&#xff09; 1.电子表格&a…

昇思25天学习打卡营第6天 | 函数式自动微分

神经网络的训练主要使用反向传播算法&#xff0c; 模型预测值&#xff08;logits&#xff09;与正确标签&#xff08;label&#xff09;送入损失函数&#xff08;loss function&#xff09;获得loss&#xff0c; 然后进行反向传播计算&#xff0c;求得梯度&#xff08;gradie…

数据中心 250KW 水冷负载组概述

该负载专为数据中心冷水机组调试和测试应用而设计, 是一款紧凑的便携式产品&#xff0c;具有无限功率和水流控制功能&#xff0c;可实现精确的温升设置与施加的功率。鹦鹉螺是完全可联网的&#xff0c;可以从远程站控制单个或多个单元。 使用带有触摸屏 HMI 的 PLC&#xff0c;…

Navicat连接Oracle出现Oracle library is not loaded的解决方法

目录 1. 问题所示2. 原理分析3. 解决方法1. 问题所示 使用Navicat链接Oracle的时候,出现如下提示:Oracle library is not loaded. 截图如下所示: 2. 原理分析 通常是由于缺少必需的 Oracle 客户端库或环境变量未正确配置所致 还有一种情况是 32位与64位的不匹配:Navica…

基于Langchain-chatchat搭建本地智能知识问答系统

基于Langchain-chatchat搭建本地智能 搭建本地智能知识问答系统&#xff1a;基于Langchain-chatchat的实践指南引言项目概述环境安装Anacondapip 项目安装步骤大语言模型&#xff08;LLM&#xff09;的重要性结语 搭建本地智能知识问答系统&#xff1a;基于Langchain-chatchat的…

记错医院预约的日期,选择加号还是回去?

记错了去医院的日期&#xff0c;起了个大早&#xff0c;用了 90 分钟才到医院&#xff0c;取号时提示没有预约的号&#xff0c;才发现记错时间了。这个时候是选择找医生加号还是直接回去呢&#xff1f;如果是你怎么选择&#xff1f; 如果选择找医生加号&#xff0c;号会排到最后…

STM32 ---- F1系列内核和芯片系统架构 || 存储器映像 || 寄存器映射

一&#xff0c;存储器映像 STM32 寻址范围&#xff1a;2^32 4 * 2^10 *2^10 K 4 * 2^10 M 4G 地址所访问的存储单元是按字节编址的。 0x0000 0000 ~ 0xFFFF FFFF 什么是存储器映射&#xff1f; 存储器本身不具有地址信息&#xff0c;给存储器分配地址的…

STM32单片机WDG看门狗详解

文章目录 1. WDG简介 2. IWDG框图 3. IWDG键寄存器 4. IWDG超时时间 5. WWDG框图 6. WWDG工作特性 7. WWDG超时时间 8. IWDG和WWDG对比 9. 代码示例 1. WDG简介 WDG&#xff08;Watchdog&#xff09;看门狗 看门狗可以监控程序的运行状态&#xff0c;当程序因为设计…

Docker Compose--安装Nginx--方法/实例

原文网址&#xff1a;Docker Compose--安装Nginx--方法/实例_IT利刃出鞘的博客-CSDN博客 简介 说明 本文介绍Docker Compose如何安装Nginx。 目录结构 ├── config │ ├── cert │ │ ├── xxx_bundle.pem │ │ └── xxx.key │ ├── conf.d │ …

【ONLYOFFICE震撼8.1】ONLYOFFICE8.1版本桌面编辑器测评

随着远程工作的普及和数字化办公的发展&#xff0c;越来越多的人开始寻找一款具有强大功能和便捷使用的办公软件。在这个时候&#xff0c;ONLYOFFICE 8.1应运而生&#xff0c;成为了许多用户的新选择。ONLYOFFICE 8.1是一种办公套件软件&#xff0c;它提供了文档处理、电子表格…

jupyter中如何看plt.plot的局部细节

在Jupyter中使用matplotlib时&#xff0c;如果你想要放大图表的某一部分&#xff0c;可以使用matplotlib的交互式方式查看局部细节。 %matplotlib notebook # 在Jupyter中使用交互式后端 import matplotlib.pyplot as plt import numpy as np# 生成数据 x np.linspace(0, 10…

TiDB 资源管控的对撞测试以及最佳实践架构

作者&#xff1a; GreenGuan 原文来源&#xff1a; https://tidb.net/blog/bc405c21 引言 TiDB 是一个存算分离的架构&#xff0c;资源管控对这种分离的架构来说实现确实有非常大的难度&#xff0c;TiDB 从 7.1 版本开始引入资源管控的概念&#xff0c;在社区也有不少伙伴测…