拓扑排序

拓扑排序的定义:

拓扑排序是在有向无环图(DAG)里按指向关系弹出一个序列,比如A->B,在序列里A就要在B的前面。官方定义:由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。

拓扑排序的性质:

  • 每个顶点出现且只出现一次。
  • 若A在序列中排在B的前面,则在图中不存在从B到A的路径。
  • DAG图必然存在一个拓扑排序。
  • 拓扑排序的序列不一定唯一。

拓扑排序的实现:

首先考虑一个问题,怎么找到DAG图的"起点"?第一个点就是应该没有其它结点指向它,只有它指向别人,所以它才会位于其它结点的前面。为此引入"入度"这个概念:

入度:某个结点被指的结点(边)数就是这个结点的入度。

也就是说一个DAG的起点就是入度为0 的结点,把当前起点在DAG的删除,新的入度为0的结点就是新图的起点,也就是接着弹出的结点。对于新起点来说,老起点已经弹出去了,不考虑老起点的影响,就算老起点原来指向了它也没有影响,它现在就是应该弹出的结点。

为什么一直存在新起点?:这是由DAG图的性质保证的。1.DAG图的子图是DAG图 2.DAG图中肯定有入度为0 的结点。

python代码实现:

def topsort(G):
    # in_degrees保存所有结点的入度
    in_degrees = dict((u, 0) for u in G)
    # 计算初始入度
    for u in G:
        for v in  G[u]:
            in_degrees[v] += 1
    # Q保存入度为 0 的节点                              
    Q = [u for u in G if in_degrees[u] == 0]
    # S是要弹出的序列
    S = []
    # 每一轮遍历所有的入度为零的结点
    while Q:
        u = Q.pop() # 默认从最后一个移除
        '''
        这块的如果从尾部弹出,下面新起点又是从尾部压入,这就是维护的一个栈,这深度优先的排序
        如果是从头部弹出,这就是队列,这是宽度优先的排序
        用一个对称的DAG图,就可以看出区别
        '''
        # 让它弹出到序列                         
        S.append(u)
        # v是入度为0指向的结点
        for v in G[u]:
            in_degrees[v] -= 1  # 并移除其指向,也就是入度减一
            # 如果入度为0,也就是新起点,保存起来。
            if in_degrees[v] == 0:
                Q.append(v)
    return S
G = {
    'a':'bf',
    'b':'cdf',
    'c':'d',
    'd':'ef',
    'e':'f',
    'f':''
}
>>> print(topsort(G))
['a', 'b', 'c', 'd', 'e', 'f']

拓扑排序的应用:

https://blog.csdn.net/qq_23262411/article/details/100034358

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值