当前位置: 首页 > news >正文

拓扑排序(算法基础)

拓扑排序

试想这样一个问题,我们做事情事情本身之间有先决条件。例如我们希望能在这些事情之间找到不破坏依赖关系的前提下对整个结果排序。这被称为拓扑排序。假设下面的例子,每个节点称为一个课程。

C1
C3
C8
C4
C2
C5
C6
C9
C7

我们学习C3则需要先学C2和C1。也就是说我们应该先学没有任何依赖的课程(没有被指向的节点)。于是我们定义节点的入度表示有多少指向其的节点。例如C3的入度为2,因为有两个节点C1和C2指向它
C3课程需要C1和C2先修课程,如果C1当前已经完成,此时想上C3则需要完成剩下的课程C2。当然我们也可以先完成C2再完成C1,也就是说拓扑排序的结果不一定是唯一的。我们上了某门课则需要将次课程指向的课程入度-1(或者也可以说将指向的边删除C1–>C3的边删除)。于是我们可以简单地总结拓扑排序

  1. 找到图中入度为0的点加入结果
  2. 将节点关联的其它节点的入度-1
  3. 在剩下节点中找到入度为0的节点重复操作1,2直到最后所有的节点入度都为0为止。

算法分析

根据上面的算法我们需要知道:

  1. 首先知道每个节点的入度值。
  2. 根据节点找到其指向的节点。
  3. 快速找到入度为0的节点。

算法流程分析

入度表:

C1C2C3C4C5C6C7C8C9
002212211

为了能顺序访问,我们将入度为0的节点放入队列。算法执行:

  1. 将入度为0的C1、C2加入队列
  2. 将队列头的C1取出,根据C1找到其相连的C3和C8节点,然后将C3和C8的入度-1。此时图如下:
C3
C4
C2
C5
C6
C8
C9
C7
C1C2C3C4C5C6C7C8C9
001212201

这时我们发现C8入度为0,加入队列。此时队列中元素为[C2,C8]
3. C2出队列,将C3和C5的入度-1。

C3
C4
C5
C6
C8
C9
C7
C1C2C3C4C5C6C7C8C9
000202201

此时C3和C5已经入度为0,入队列,此时队列中元素[C8,C3,C5]
4. C8出队列,然后C9入度-1

C3
C4
C5
C6
C9
C7
C1C2C3C4C5C6C7C8C9
000202200

此时C9入度为0,将C9加入队列。此时队列中[C3,C5,C9]
5. C3出队列,C4入度-1

C5
C4
C6
C9
C7
C1C2C3C4C5C6C7C8C9
000102200

此时没有节点入度为0,则不需加入任何节点到队列中。队列中元素[C5,C9]
6. C5出队列,C4和C6入度-1

C4
C6
C9
C7
C1C2C3C4C5C6C7C8C9
000001200

此时C4入度为0,将C4加入队列。队列中元素[C9,C4]
7. C9出队列,C7入度-1。

C4
C6
C7
C1C2C3C4C5C6C7C8C9
000001100

此时队列中元素为C4
8. C4出队列,C6、C7入度-1。

C7
C6
C1C2C3C4C5C6C7C8C9
000000000

此时C6和C7入度都为0,将其加入队列,此时队列元素[C6,C7]
9.最后C6、C7出队列。队列为空,则可以拓扑排序。

什么样的情况无法拓扑排序?

C4
C6
C7

此时没有节点入度为0。核心在于C4课程依赖于C7,而C7同样依赖于C4。

实践

def canFinish(numCourses: int, prerequisites: List[List[int]]) -> bool:
    node_link_nodes = {}
    node_indgree = {}
    indegree = set()
    for node in prerequisites:
        if node[1] not in node_indgree:
            node_indgree[node[1]] = 1
        else:
            node_indgree[node[1]] += 1
        # 入度不为0的节点加入indegree
        indegree.add(node[1])
        if node[0] not in node_link_nodes:
            node_link_nodes[node[0]] = [node[1]]
        else:
            node_link_nodes[node[0]].append(node[1])
    nodes = deque(set(range(numCourses)) - indegree)
    out = []
    while len(nodes) > 0:
        no_indegree = nodes.popleft()
        out.append(no_indegree)
        if no_indegree in node_link_nodes:
            for node in node_link_nodes[no_indegree]:
                node_indgree[node] -= 1
                if node_indgree[node] == 0:
                    nodes.append(node)
    return len(out) == numCourses
 def findOrder(numCourses: int, prerequisites: List[List[int]]) -> List[int]:
    indegree = [0] * numCourses
    # 节点和其连接的相邻节点
    adj = {}
    res = []
    for edge in prerequisites:
        indegree[edge[0]] += 1

    for x, y in prerequisites:
        if y not in adj:
            adj[y] = []
        adj[y].append(x)

    visited = [False for i in range(numCourses)]
    node_indeies = []

    for node_index, value in enumerate(indegree):
        if value == 0 and not visited[node_index]:
            node_indeies.append(node_index)
            visited[node_index] = True
    while len(node_indeies) > 0:
        joined_node = node_indeies.pop(0)
        res.append(joined_node)
        if joined_node in adj:
            for related_index in adj[joined_node]:
                indegree[related_index] -= 1
                if indegree[related_index] == 0 and not visited[related_index]:
                    node_indeies.append(related_index)
                    visited[related_index] = True

        if joined_node in adj:
            adj.pop(joined_node)
    return res if len(res) == numCourses else []


相关文章:

  • 针对信息化软硬件设备:常用询价网站是否够用
  • 【Unity3D脚本与系统设计6】鼠标触摸超时待机实现
  • 全排列 | 下一个排列
  • CSS3学习教程,从入门到精通,CSS3 浮动与清除浮动语法知识点及案例代码(14)
  • 计算机二级:文件操作
  • C语言部分代码
  • 深入理解指针(2)(C语言版)
  • MySQL基本函数
  • UE4学习笔记 FPS游戏制作20 重写机器人和玩家死亡 切换相机和模型
  • 【leetcode hot 100 739】每日温度
  • 关系图:赋能数据可视化的动态扩展
  • 微服务中的服务发现与注册中心
  • python之网络编程
  • zabbix添加IIS网站计数器(并发连接数)
  • jupyter使用过程中遇到的问题
  • 硬件学习笔记--53 DC-DC Buck工作原理、选型及应用介绍
  • <KeepAlive>和<keep-alive>有什么区别
  • LiblibAI 接入阿里通义大模型,推出 10 秒 AI 视频生成功能
  • 汽车加气站操作工题目及答案解析
  • 算法学习第十六天:动态规划(补充题目)
  • 做投票页面什么网站好/seo关键词优化策略
  • 用安卓手机做网站主机/怎么找关键词
  • 杭州网站设计公司有哪些/网站seo服务
  • 网站打不开 清理缓存后可以打开/安徽seo报价
  • 网站获得流量最好的方法是什么 ( )/市场营销教材电子版
  • 桂林做网站的公司有哪些/个人网站网页首页