首页 > 编程语言 >数据结构与算法 头歌 图的拓扑排序算法

数据结构与算法 头歌 图的拓扑排序算法

时间:2023-07-19 19:39:07浏览次数:38  
标签:node 排序 graph 拓扑 入度 头歌 算法 数据结构 节点

数据结构与算法之图的拓扑排序算法

导言

拓扑排序是对有向无环图(Directed Acyclic Graph, DAG)进行排序的一种算法。在实际开发中,拓扑排序算法常用于解决任务调度、编译顺序等问题。本文将介绍拓扑排序算法的实现过程,并帮助初学者理解该算法的原理及代码实现。

拓扑排序流程

以下是拓扑排序算法的流程,用表格展示每个步骤的具体内容。

步骤 描述
初始化 创建图的邻接表表示,记录每个节点的入度
构建邻接表 将图的边信息添加到邻接表中
计算入度 遍历邻接表,统计每个节点的入度
将入度为0的节点入队 将所有入度为0的节点加入队列中
拓扑排序 从队列中取出一个节点,输出该节点;然后更新其相邻节点的入度,若入度减为0,则加入队列中
判断是否有环 若队列为空,但还有未输出的节点,则存在环

代码实现

现在,我们来一步步实现拓扑排序算法,并给出相应代码及注释。

from collections import deque

def topological_sort(graph):
    # 初始化
    in_degree = {node: 0 for node in graph}
    adjacency_list = {node: [] for node in graph}
    
    # 构建邻接表
    for node in graph:
        for neighbor in graph[node]:
            adjacency_list[node].append(neighbor)
    
    # 计算入度
    for node in adjacency_list:
        for neighbor in adjacency_list[node]:
            in_degree[neighbor] += 1
    
    # 将入度为0的节点入队
    queue = deque()
    for node in in_degree:
        if in_degree[node] == 0:
            queue.append(node)
    
    # 拓扑排序
    result = []
    while queue:
        node = queue.popleft()
        result.append(node)
        for neighbor in adjacency_list[node]:
            in_degree[neighbor] -= 1
            if in_degree[neighbor] == 0:
                queue.append(neighbor)
    
    # 判断是否有环
    if len(result) != len(graph):
        raise ValueError("The graph contains cycles.")
    
    return result

以上代码实现了拓扑排序算法,具体步骤如下:

  1. 初始化:创建图的邻接表表示adjacency_list,记录每个节点的入度in_degree
  2. 构建邻接表:遍历图的每个节点,将其邻居节点加入邻接表中。
  3. 计算入度:遍历邻接表,统计每个节点的入度。
  4. 将入度为0的节点入队:遍历入度表,将入度为0的节点加入队列中。
  5. 拓扑排序:从队列中取出一个节点,输出该节点;然后更新其相邻节点的入度,若入度减为0,则加入队列中。
  6. 判断是否有环:若队列为空,但还有未输出的节点,则表示图中存在环。

注意事项:上述代码中,我们使用了deque来实现队列数据结构。可以通过pip install collections来安装collections库。

使用示例

现在,我们来演示一下使用上述代码进行拓扑排序的示例。假设我们有以下有向图:

graph = {
    'A': ['C', 'D'],
    'B': ['D'],
    'C': ['E'],
    'D': ['E', 'F'],
    'E': ['F'],
    'F': []
}

我们将使用topological_sort(graph)函数对该图进行拓扑排序操作,代码如下:

graph = {
    'A': ['C', 'D'],
    'B': ['D'],
    'C': ['E'],
    'D': ['E', 'F'],
    'E': ['F'],
    'F': []
}

try:
    result = topological_sort(graph)
    print("拓扑排序结果:", result)
except ValueError as

标签:node,排序,graph,拓扑,入度,头歌,算法,数据结构,节点
From: https://blog.51cto.com/u_16175446/6779254

相关文章

  • KMP算法笔记
    1.概念解析前置:将原串称之为文本串,匹配串称之为模式串。KMP的实质其实就是:利用已经匹配的信息,来加速查找的过程。对于暴力解法而言,当我进行模式串匹配时,遇到一个不匹配的字符,那么只能一步一步往下滑动,然后重新匹配。但是对于KMP算法而言,利用到了前缀子......
  • 最短路之dijkstra算法
    dijkstra比之上次介绍的的bellman-ford算法的用途上最大的区别就是dijkstra只可用于求无负权边图中的最短路,堆优化后的dij比bellman-ford的复杂度(mn)更小(mlogn)代码源关于dijkstra的解释简单来讲就是每次选出一个没被选过的离起点最近的点,松弛这个点所在的每个边,直到所有点都被......
  • 最短路之 Bellman-ford 算法
    bellman-ford算法的思想:若有向图有n个点,m条边。扫描所有边,对每条边进行一次松弛(即对a,b为端点,权重为w的边,dist[b]=min(dist[a],dist[a]+w))重复此流程(最多重复n次)直到没有更新操作发生例题1bellmanford板子给你一张n个顶点m条边的有向简单图,顶点编号从1到......
  • C/C++数据结构课程设计题目[2023-07-19]
    C/C++数据结构课程设计题目[2023-07-19]数据结构课程设计题目基本要求:1、每人1题,如果系统具有界面以及功能复杂,可以2人合作一题。2、可以自拟题目,难度不低于给定题目,且自拟的题目需要经过老师审核通过。3、要求实现一个界面美观、功能完整、具有实用性的系统。4、不限制......
  • 历年检测、分割、生成算法梳理(2023)
    检测算法 分割算法 生成算法 ......
  • 雷达算法 | 一种适用于汽车雷达的聚类算法研究与分析
    公众号【调皮连续波】,其他平台为自动同步,同步内容若有不全或乱码,请前往公众号阅读。保持关注调皮哥,获得更多雷达干货学习资料和建议,助力大家轻松、快乐、有方向地学习雷达技术。本文参考TI的一种适用于汽车雷达的聚类算法研究和实现.pdf文档由于不涉及硬件,因此本文仅对算法部分进行......
  • 校招 | 2023届应届生毫米波雷达算法岗秋招经历分享
    本文首发于公众号【调皮连续波】,其他平台为自动同步,同步内容若有不全或乱码,请前往公众号阅读。保持关注调皮哥,获得更多雷达干货学习资料和建议,助力大家轻松、快乐、有方向地学习雷达技术。知乎:https://zhuanlan.zhihu.com/p/576656211。原创作者: @探索Seeker本文经过原创作者同意,......
  • 字典树(trie) 算法笔记
    P1字典树是什么顾名思义就像一个字典一样,可以查询某单词是否出现,也可以查找同一前缀的单词的个数等等操作。P2字典树的实现字典树是用树来实现的(这不废话吗),如果从根节点走到一个已标记过的节点(后面我们会称它为单词节点)的一条路径就是一个单词。我们定义一下变量(或数组)的表......
  • 数据结构--二叉平衡树
    二叉平衡树回顾:二叉排序树的查找二叉排序树的不平衡会影响查找效率,所有我们要尽量让二叉树的形态均衡.AVL树(平衡二叉树)必须是二叉排序树左子树和右子树的高度之差的绝对值小于等于1左子树和右子树也是平衡二叉排序树平衡因子该结点左子树与右子树的高度差.平......
  • 代码随想录算法训练营第三十三天| 1049. 最后一块石头的重量 II 494. 目标和 474.一
    1049.最后一块石头的重量II思路:因为含有两个石头的相撞,所以需要把dp的目标值改成sum/2,然后取得这个目标值的最大值,然后对sum-2*target代码:1//要求:有多个石头,两两撞击,取得剩下的石头的最小值2//——》一定要碰到最后一个3//注意:4//1,x==y:两个粉碎,x<y:y=......