排序-拓扑
拓扑排序:对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,
是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),
则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。
在图论中,由一个有向无环图的顶点组成的序列,当且仅当满足下列条件时,称为该图的一个拓扑排序
(英语:Topological sorting):每个顶点出现且只出现一次;
若A在序列中排在B的前面,则在图中不存在从B到A的路径
结论:
(1)拓扑排序并不唯一
(2)不含回路的有向图(有向无环图)——一定存在拓扑排序。
Python 代码实现:
# v表示图中的各顶点,e表示两个顶点之间的边 def inDegree0(v,e): # 如果顶点为空或者已经没有需要处理的顶点 if len(v) == 0: return None # 把v列表的内容复制给tmp变量,第一次tmp = ['a'] tmp = v[:] # 遍历e列表中的每一个元组,第1个元组:('a','b'), # 如果每个元组中[1]位置的值存在tmp列表的,则说明这个顶点入度不是0,也就说存在一条带方向指向其顶点的边 # 经历第一次遍历后,tmp列表的内容就是剩下入度是0的顶点 for i in e: if i[1] in tmp: tmp.remove(i[1]) # 如果不存在入度是0的列表,则说明存在环路,没法计算拓扑排序 if tmp == []: return -1 for t in tmp: # 对e列表中,如果包含'a'顶点的,则把其值替换为'toDel' # ['toDel', 'toDel', ('b', 'c'), ('d', 'c'), ('d', 'e'), ('e', 'c')] for i in range(len(e)): if t in e[i]: e[i] = 'toDel' # 占位,之后删掉 if e: # set 和 dict 类似,也是一组 key 的集合,但是不存储 value. 由于 key 不重复 # set是一组数,无序,内容又不能重复,相当于去掉重复的'toDel' # {'toDel', ('d', 'c'), ('b', 'c'), ('d', 'e'), ('e', 'c')} eset = set(e) # {('d', 'c'), ('b', 'c'), ('d', 'e'), ('e', 'c')} eset.remove('toDel') # 把集合转换为列表 # [('d', 'c'), ('b', 'c'), ('d', 'e'), ('e', 'c')] e[:] = list(eset) # 把刚才处理的a顶点从v列表中移除 # v=['b', 'c', 'd', 'e'] if v: for t in tmp: v.remove(t) return tmp def topoSort(v,e): result = [] while True: nodes = inDegree0(v, e) if nodes == None: break if nodes == -1: print('there\'s a circle.') return None # 用于在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)。 result.extend(nodes) return result v=['a','b','c','d','e'] e=[('a','b'),('a','d'),('b','c'),('d','c'),('d','e'),('e','c')] res=topoSort(v,e) print(res)