遇到如下场景: 有这样一组依赖关系列表如下:
1:A->[B,C]
2:B->[D]
3:C->[E]
箭头左边是被依赖项, 箭头右边是依赖项列表.
现在需要将这个关系按照被依赖项在依赖项前进行排序. 比如上面的例子正常的一个排序结果应该是A,B,C,D,E. 本文就详细讲解这里涉及到的完成这一目的的排序算法——拓扑排序.
拓扑排序(topological sort)介绍
按照wiki拓扑排序的说法,拓扑排序是对有向无环图的顶点的线性排序,要求对于顶点u到v的每一个有向边uv顶点u都在v前面.
拓扑排序其中一个重要的场景就是对互相有依赖的任务的执行顺序排序
拓扑排序算法
kahn卡恩算法
1962年卡恩提出此算法,算法描述:假设L是存放结果的列表,先找到那些入度为零的节点,把这些节点放到L中,因为这些节点没有任何的父节点。然后把与这些节点相连的边从图中去掉,再寻找图中的入度为零的节点。对于新找到的这些入度为零的节点来说,他们的父节点已经都在L中了,所以也可以放入L。重复上述操作,直到找不到入度为零的节点。如果此时L中的元素个数和节点总数相同,说明排序完成;如果L中的元素个数和节点总数不同,说明原图中存在环,无法进行拓扑排序.
L ← 包含已排序的元素的列表,目前为空
S ← 入度为零的节点的集合
当 S 非空时:
将节点n从S移走
将n加到L尾部
选出任意起点为n的边e = (n,m),移除e。如m没有其它入边,则将m加入S。
重复上一步。
如图中有剩余的边则:
return error (图中至少有一个环)
否则:
return L (L为图的拓扑排序)
首先是对输入数据格式的要求,一般在kahn算法里面用字典(临接表)表示整个图,字典的key是图中边的起点节点,key对应的value则是边的终点节点的list. 如果在编排dependency 任务执行顺序的场景,那么key就是被依赖任务,而value则是依赖此任务的后续执行任务的列表.
举个例子,有如下dag需要进行拓扑排序.
图数据一般的原始输入都是用元祖表示的边的list, 比如上图就可以表示为
src_graph = [('a','b'),('a','c'),('b','d'),('c','e')]
需要将原始图数据转换为字典:
from collections import defaultdict
src_graph = [('A','B'),('A','C'),('B','D'),('C','E')]
data = defaultdict


433

被折叠的 条评论
为什么被折叠?



