【JavaScript 算法】拓扑排序:有向无环图的应用

在这里插入图片描述

🔥 个人主页:空白诗

在这里插入图片描述

文章目录

    • 一、算法原理
    • 二、算法实现
      • 方法一:Kahn算法
      • 方法二:深度优先搜索(DFS)
      • 注释说明:
    • 三、应用场景
    • 四、总结

在这里插入图片描述

拓扑排序(Topological Sorting)是一种线性排序方法,适用于有向无环图(DAG, Directed Acyclic Graph),它能够为图中的节点安排一个线性序列,使得对于图中的每一条有向边(u, v),顶点u在序列中出现在顶点v之前。拓扑排序在许多实际应用中都有重要作用,如任务调度、课程安排、编译依赖等。本文将详细介绍拓扑排序的原理、实现及其应用。


一、算法原理

拓扑排序的基本思想是:

  1. 选择一个入度为0的节点,将其输出到排序结果,并从图中删除该节点及其关联的所有边。
  2. 重复步骤1,直到所有节点都被输出,或者图中仍存在入度不为0的节点(此时图中存在环,无法进行拓扑排序)。

常用的两种实现拓扑排序的方法是Kahn算法和深度优先搜索(DFS)。


二、算法实现

方法一:Kahn算法

DFS

Kahn算法利用队列实现拓扑排序,通过不断删除入度为0的节点来构建拓扑序列。

/*** Kahn算法实现拓扑排序* @param {Object} graph - 图的邻接表表示* @return {string[]} - 拓扑排序结果*/
function kahnTopologicalSort(graph) {const inDegree = {}; // 记录每个节点的入度const queue = []; // 存储入度为0的节点const result = []; // 存储拓扑排序结果// 初始化入度表for (const node in graph) {inDegree[node] = 0;}// 计算每个节点的入度for (const node in graph) {for (const neighbor of graph[node]) {inDegree[neighbor]++;}}// 将入度为0的节点加入队列for (const node in inDegree) {if (inDegree[node] === 0) {queue.push(node);}}// 处理队列中的节点while (queue.length > 0) {const node = queue.shift(); // 取出队首节点result.push(node); // 将节点加入拓扑排序结果// 减少相邻节点的入度for (const neighbor of graph[node]) {inDegree[neighbor]--;// 如果相邻节点的入度为0,加入队列if (inDegree[neighbor] === 0) {queue.push(neighbor);}}}// 检查是否存在环if (result.length !== Object.keys(graph).length) {throw new Error("图中存在环,无法进行拓扑排序");}return result;
}// 示例
const graph = {A: ['C'],B: ['C', 'D'],C: ['E'],D: ['F'],E: ['H', 'F'],F: ['G'],G: [],H: []
};console.log(kahnTopologicalSort(graph)); // 输出: [ 'A', 'B', 'D', 'C', 'E', 'F', 'H', 'G' ]

方法二:深度优先搜索(DFS)

DFS

DFS方法通过递归遍历图,将访问过的节点存入栈中,最终从栈顶依次取出节点构建拓扑序列。

/*** 深度优先搜索实现拓扑排序* @param {Object} graph - 图的邻接表表示* @return {string[]} - 拓扑排序结果*/
function dfsTopologicalSort(graph) {const visited = new Set(); // 记录已访问的节点const stack = []; // 存储拓扑排序结果/*** 递归函数:DFS遍历节点* @param {string} node - 当前节点*/function dfs(node) {if (visited.has(node)) return;visited.add(node); // 标记节点为已访问for (const neighbor of graph[node]) {dfs(neighbor); // 递归访问相邻节点}stack.push(node); // 当前节点处理完毕,加入栈中}// 遍历所有节点,进行DFSfor (const node in graph) {dfs(node);}return stack.reverse(); // 返回栈的逆序,即拓扑排序结果
}// 示例
console.log(dfsTopologicalSort(graph)); // 输出: [ 'B', 'D', 'A', 'C', 'E', 'H', 'F', 'G' ]

注释说明:

  1. Kahn算法

    • inDegree:记录每个节点的入度。
    • queue:存储入度为0的节点。
    • result:存储拓扑排序结果。
    • 初始化入度表,并计算每个节点的入度。
    • 将入度为0的节点加入队列,处理队列中的节点,更新相邻节点的入度。
    • 最终检查是否存在环,返回拓扑排序结果。
  2. DFS方法

    • visited:记录已访问的节点。
    • stack:存储拓扑排序结果。
    • 递归遍历节点,将访问过的节点存入栈中,最终返回栈的逆序。

三、应用场景

  1. 任务调度:根据任务之间的依赖关系,确定任务的执行顺序。
  2. 课程安排:根据课程的先修关系,确定课程的学习顺序。
  3. 编译依赖:根据文件的依赖关系,确定编译的顺序。
  4. 数据处理:根据数据的依赖关系,确定处理的顺序。

四、总结

拓扑排序是一种用于有向无环图(DAG)的线性排序方法,通过Kahn算法和DFS方法可以实现拓扑排序,广泛应用于任务调度、课程安排、编译依赖和数据处理等场景。理解和掌握拓扑排序算法,对于解决实际问题具有重要意义。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/48116.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

核函数支持向量机(Kernel SVM)

核函数支持向量机(Kernel SVM)是一种非常强大的分类器,能够在非线性数据集上实现良好的分类效果。以下是关于核函数支持向量机的详细数学模型理论知识推导、实施步骤与参数解读,以及两个多维数据实例(一个未优化模型&a…

笔记 3 : 继续彭老师课本第 3 章的 arm 的汇编指令

(26) 指令 LDR : (27) STR : 可见,从语法上将, ! 提示编译器进行更复杂的编译,对应内涵更复杂的指令。 (28) LDR 与 STR 指令还可…

Android C++系列:Linux信号(三)

可重入函数 不含全局变量和静态变量是可重入函数的一个要素可重入函数见man 7 signal在信号捕捉函数里应使用可重入函数在信号捕捉函数里禁止调用不可重入函数例如:strtok就是一个不可重入函数,因为strtok内部维护了一个内部静态指针,保存上一 次切割到的位置,如果信号的捕捉…

RK3588 编译opencvopencv_contrib记录

RK3588 编译opencv&opencv_contrib记录 1. 下载文件1.1 opencv源码1.2 安装cmake 2.开始编译2.1 提示缺少boostdesc_bgm.i 等问题2.2 提示缺少某hpp头文件2.3 其它问题 3. 设置环境变量4. 测试5.参考 1. 下载文件 1.1 opencv源码 需要opencv和opencv-contrib的版本号保持…

echarts实现3d柱状效果

代码如下,单个的调第一个方法,多个柱状的调第二个方法,具体情况修改参数或者二次开发即可 //3d柱状图 export function getEcharts3DBar (xAxisData:string[][name1,name2,name3], data:number[][1,2,3], colorObj:IBaseObject{topStartColo…

Go的入门

一、GO简介 Go语言(也叫 Golang)是Google开发的开源编程语言。 1. 语言特性 Go 语法简洁,上手容易,快速编译,支持跨平台开发,自动垃圾回收机制,天生的并发特性,更好地利用大量的分…

服务器相关总结

文章目录 conda 安装镜像源总结(手动加)创建环境安装pytorch安装transformers conda 安装 查看conda版本 conda --version查看当前conda的配置文件位置 conda config --show编辑配置文件,默认路径是~/condarc vim ~/.condarc 在channels字段添加新的…

通过albumentation对目标检测进行数据增强(简单直接)

albumentation官方文档看不懂?xml文件不知道如何操作?下面只需要修改部分代码即可上手使用 要使用这个方法之前需要按照albumentation这个库还有一些辅助库,自己看着来安装就行 pip install albumentation pip install opencv-python pip install json…

MKS流量计软件MFC通讯驱动使用于C和P系列MFC控制USB接口W10系统

MKS流量计软件MFC通讯驱动使用于C和P系列MFC控制USB接口W10系统

使用VuePress-Reco快速搭建博客(保姆级)

简介:VuePress-Reco 一款简洁的 vuepress 博客 & 文档 主题,可以自由搭建自己的风格,比较方便简洁。 链接:vuepress-reco 准备环境: Node.Js >20.5.0,Npm > 10.8.2 OR Yarn > 1.22.19 注&am…

Android C++系列:Linux信号(二)

PCB的信号集 如果在进程解除对某信号的阻塞之前这种信号产生过多次,将如何处理?POSIX.1允 许系统递送该信号一次或多次。Linux是这样实现的:常规信号在递达之前产生多次只 计一次,而实时信号在递达之前产生多次可以依次放在一个队列里。本文不讨论实时信 号。每个信号只有一…

Kafka介绍及Go操作kafka详解

文章目录 Kafka介绍及Go操作kafka详解项目背景解决方案面临的问题业界方案ELKELK方案的问题日志收集系统架构设计架构设计组件介绍将学到的技能消息队列的通信模型点对点模式 queue发布/订阅 topicKafka介绍Kafka的架构图工作流程选择partition的原则ACK应答机制Topic和数据日志…

0718,TCP协议,三次握手,四次挥手

目录 上课喵: TCP(Transmission Control Protocol,传输控制协议)的状态迁移图 TCP连接的状态迁移图 状态迁移说明: 注意: big_htonl.c 字节序转换 addr.c IP地址的转换 作业喵: …

django命令

Django 的命令行工具 django-admin(或 manage.py 中的 manage 函数)提供了一系列的命令,用于执行各种管理任务。 1. check: 检查项目的 full 路径,确保没有错误配置。 2. compilemessages: 编译 .po 文件中的翻译,生…

Python面试整理-Python中的控制流语句

在Python中,控制流语句用于根据特定的条件或逻辑来控制程序的执行流程。主要的控制流语句包括条件判断(if)、循环(for 和 while)以及其他辅助语句如 break, continue, 和 pass。下面详细介绍这些控制流语句: 1. 条件判断(if 语句) if 语句用于根据一个或多个条件来执行…

前端组件化实践:Vue自定义加载Loading组件的设计与实现

摘要 随着前端技术的飞速发展,组件化开发已成为提高开发效率、降低维护成本的重要方法。本文介绍了前端Vue自定义加载Loading组件的设计思路与实现过程,该组件通过设置gif动画实现加载效果,可广泛应用于页面请求加载场景。通过该组件的实践&…

2024年度上半年中国汽车保值率报告

来源:中国汽车流通协会&精真估 近期历史回顾: 2024上半年房地产企业数智化转型报告.pdf 2024国产院线电影路演数据洞察报告.pdf 空间数据智能大模型研究-2024年中国空间数据智能战略发展白皮书.pdf 2024年全球资产管理报告 2024年中型律师事务所的法…

VMware中Ubuntu磁盘空间的清理

最近发现Ubuntu占用空间过大,在网上找了一些方法,在这里总结一下。 1.删除快照 把不需要的快照删除,但要注意删除快照可能会影响到后续的快照链。每个快照依赖于前面的快照。如果删除一个中间快照,虚拟机可能无法找到完整的差异…

深入解析Linux文件权限管理:掌握`chmod`和`chown`命令

深入解析Linux文件权限管理:掌握chmod和chown命令 深入解析Linux文件权限管理:掌握chmod和chown命令 大纲:摘要:内容: 1. 引言2. 理解文件权限3. 使用chmod命令4. 使用chown命令5. 综合应用6. 常见问题与解决方案7. 结…

零基础入门:创建一个简单的Python爬虫管理系统

摘要: 本文将手把手教你,从零开始构建一个简易的Python爬虫管理系统,无需编程基础,轻松掌握数据抓取技巧。通过实战演练,你将学会设置项目、编写基本爬虫代码、管理爬取任务与数据,为个人研究或企业需求奠…