拓扑排序算法
创始人
2024-03-05 09:10:27
0

背景

拓扑排序是啥意思?

拓扑排序是指: 将有向无环图(DAG)展开为一维的执行序列。DAG顾名思义就是有方向的图,下面这张图就简单说明了啥是有向无环图。一般人可能用到这个算法的情况不多,但是刷leetcode的课程表问题肯定遇到过,其次搞人工智能的同学静态图执行顺序也不应该陌生。
在这里插入图片描述

算法流程

先简单分析,从上面的图可以知道,要执行3节点,依赖0,1, 所以需要先执行完0,1。依次类推可以有一下的执行顺序:

  • [0,1,2,3,4,5]
  • [0,2,1,3,4,5]
  • [0,1,2,4,3,5]

此外还有很多排序方式,可见拓扑图的排序有很多选择,只要满足执行依赖要求都是可行的拓扑排序。接下来正式分析一下算法流程:

  1. 入度数组:这里需要增加两个概念:入度和出度,入度是指该节点有几个输入,出度是指该节点有几个输出。根据上面的铺垫可以很容易想到,入度为0的节点当下是可以执行的,毕竟他没有什么依赖。所以我们可以搞一个入度数组,记录每个节点的入度个数,如果当下的入度个数为0,那么该节点就是当下可以执行。
  2. 邻接表:根据上面的图我们知道,当0,1节点执行完后,节点2的入度也就变成0了,所以每个节点执行完,都应该更新一波入度数组,那么怎么更新了?这就依赖邻接表来完成,这里邻接表是一个map>,其中key是节点名node,value是依赖该key_node的节点们,也就是说把key_node作为入度之一的节点。

代码

//入度数组
vector TopologyDfsSort(graph)
{vector in_degree(n,0);init(in_degree, graph);//邻接表unordered_map> map;init(map, graph);//当下可执行的节点集合vector res;// 每次跟新的队列queue q;for(int i=0; iif(in_degree[i]==0) {q.push(i);//入度为0的都可以执行res.push(i);//入度为0的都可以执行}}//更新while(!q.empty()){//一轮执行size个节点,q中是表示该轮可以执行的节点int size = q.size();for(int i=0; iint exec_node = q.front();q.pop();//一旦exec_node执行,那么依赖exec_node的node的入度值都可以减一vector nodes = map[exec_node];for(auto id:nodes){in_degree[id]--;if(in_degree[id]==0)//如果入度为0,那么就可以进入下一轮执行{q.push(id);//入度为0的都可以执行res.push(id);//入度为0的都可以执行}}}}return res;
}

实战

可以参考paddlepaddle源码中的实现:
paddle/fluid/framework/ir/graph_helper.cc:266L

相关内容

热门资讯

前端-session、jwt 目录:   (1)session (2&#x...
linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
nodejs:本地安装nvm实... 一、背景-使用不同版本node的原因 vue3+ts、nuxt3版本,node...
JAVA集合知识整理 Java集合知识整理 HashMap相关 HashMap的底层数据结构:jdk1.8之...
无刷直流电机介绍及单片机控制实... 无刷直流电机介绍及单片机控制实例前言基本概念优势与劣势使用寿命基本结构使用单片机控制实例电子调速器&...
fwdiary(2) dp2 1.传纸条  AcWing 275. 传纸条 - AcWing 走两条路,走一条最大的...
常用的DOS命令 常用的DOS命令 DOS(Disk Operating System,磁...
<C++> 类和对象(下) 1.const成员函数将const修饰的“成员函数”称之为const成员函数,cons...