拓扑排序问题

来源:互联网 发布:rlg网络用语什么意思 编辑:程序博客网 时间:2024/06/03 19:52

拓扑排序:

几乎在所有的项目中,待完成的任务之间通常都会存在着某些依赖关系,这些关系会对它们的执行顺序形成部分约束。

对于这种依赖关系,我们通常很容易将其表示成一个有向无环路图(DAG),并将寻找其中依赖顺序的过程(寻找所有沿着特定顺序前进的边与点)成为拓扑排序(topological sorting)


解决思路:

如何归简?

首先移除其中一个节点,然后解决其余n-1个节点的问题。但,这首先要保证移除之后还是一个DAG。就是移除哪些没有入边的节点。

而清单4-9中的程序naive_topsort每次移除的都是任意的节点,这并不能保证剩余的节点还是一个DAG。清单4-10满足这样的条件,用count计数,记录每个结点的指向自己的节点个数{'a': 0, 'b': 1, 'c': 1, 'd': 2, 'e': 1, 'f': 4}

然后逐个移除count中计数为0的节点。

代码:

def naive_topsort(G, S=None):    if S is None: S = set(G) # Default: All nodes    print(S)    if len(S) == 1: return list(S) # Base case, single node    v = S.pop() # Reduction: Remove a node    seq = naive_topsort(G, S) # Recursion (assumption), n-1    min_i = 0    print("seq"," ",seq)    for i, u in enumerate(seq):        if v in G[u]: min_i = i+1 # After all dependencies    print(min_i,' ',v)    seq.insert(min_i, v)    print(seq)    return seqdef topsort(G):    count = dict((u, 0) for u in G) # The in-degree for each node    for u in G:        for v in G[u]:            count[v] += 1 # Count every in-edge    print(count)    Q = [u for u in G if count[u] == 0] # Valid initial nodes    S = [] # The result    while Q: # While we have start nodes...        u = Q.pop() # Pick one        S.append(u) # Use it as first of the rest        for v in G[u]:            count[v] -= 1 # "Uncount" its out-edges            if count[v] == 0: # New valid start nodes?                Q.append(v) # Deal with them next    return Sif __name__=="__main__":    G={        'a':set('bf'),        'b':set('cdf'),        'c':set('d'),        'd':set('ef'),        'e':set('f'),        'f':set('')           }    seq=naive_topsort(G)    print(seq)    seq2=topsort(G)    print(seq2)

运行结果:

{'d', 'e', 'c', 'f', 'a', 'b'}{'e', 'c', 'f', 'a', 'b'}{'c', 'f', 'a', 'b'}{'f', 'a', 'b'}{'a', 'b'}{'b'}seq   ['b']0   a['a', 'b']seq   ['a', 'b']2   f['a', 'b', 'f']seq   ['a', 'b', 'f']2   c['a', 'b', 'c', 'f']seq   ['a', 'b', 'c', 'f']0   e['e', 'a', 'b', 'c', 'f']seq   ['e', 'a', 'b', 'c', 'f']4   d['e', 'a', 'b', 'c', 'd', 'f']['e', 'a', 'b', 'c', 'd', 'f']{'a': 0, 'b': 1, 'c': 1, 'd': 2, 'e': 1, 'f': 4}['a', 'b', 'c', 'd', 'e', 'f']

由程序得出,《Python算法教程》中的清单4-9naive_topsort并不能总是得到正确的拓扑排序的结果。

清单4-10topsort是可以得到正确结果的。




原创粉丝点击