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


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

拓扑排序(Topological Sorting)是一种线性排序方法,适用于有向无环图(DAG, Directed Acyclic Graph),它能够为图中的节点安排一个线性序列,使得对于图中的每一条有向边
(u, v),顶点u在序列中出现在顶点v之前。拓扑排序在许多实际应用中都有重要作用,如任务调度、课程安排、编译依赖等。本文将详细介绍拓扑排序的原理、实现及其应用。
一、算法原理
拓扑排序的基本思想是:
- 选择一个入度为0的节点,将其输出到排序结果,并从图中删除该节点及其关联的所有边。
- 重复步骤1,直到所有节点都被输出,或者图中仍存在入度不为0的节点(此时图中存在环,无法进行拓扑排序)。
常用的两种实现拓扑排序的方法是Kahn算法和深度优先搜索(DFS)。
二、算法实现
方法一:Kahn算法
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方法通过递归遍历图,将访问过的节点存入栈中,最终从栈顶依次取出节点构建拓扑序列。
/*** 深度优先搜索实现拓扑排序* @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' ]
注释说明:
-
Kahn算法:
inDegree:记录每个节点的入度。queue:存储入度为0的节点。result:存储拓扑排序结果。- 初始化入度表,并计算每个节点的入度。
- 将入度为0的节点加入队列,处理队列中的节点,更新相邻节点的入度。
- 最终检查是否存在环,返回拓扑排序结果。
-
DFS方法:
visited:记录已访问的节点。stack:存储拓扑排序结果。- 递归遍历节点,将访问过的节点存入栈中,最终返回栈的逆序。
三、应用场景
- 任务调度:根据任务之间的依赖关系,确定任务的执行顺序。
- 课程安排:根据课程的先修关系,确定课程的学习顺序。
- 编译依赖:根据文件的依赖关系,确定编译的顺序。
- 数据处理:根据数据的依赖关系,确定处理的顺序。
四、总结
拓扑排序是一种用于有向无环图(DAG)的线性排序方法,通过Kahn算法和DFS方法可以实现拓扑排序,广泛应用于任务调度、课程安排、编译依赖和数据处理等场景。理解和掌握拓扑排序算法,对于解决实际问题具有重要意义。
相关文章:
【JavaScript 算法】拓扑排序:有向无环图的应用
🔥 个人主页:空白诗 文章目录 一、算法原理二、算法实现方法一:Kahn算法方法二:深度优先搜索(DFS)注释说明: 三、应用场景四、总结 拓扑排序(Topological Sorting)是一种…...
Fastgpt本地或服务器私有化部署常见问题
一、错误排查方式 遇到问题先按下面方式排查。 docker ps -a 查看所有容器运行状态,检查是否全部 running,如有异常,尝试docker logs 容器名查看对应日志。容器都运行正常的,docker logs 容器名 查看报错日志带有requestId的,都是 OneAPI 提示错误,大部分都是因为模型接…...
基于深度学习的股票预测
基于深度学习的股票预测是一项复杂且具有挑战性的任务,涉及金融数据的分析和预测。其目的是利用深度学习模型来预测股票价格的走势,从而帮助投资者做出更为准确的投资决策。以下是对这一领域的系统介绍: 1. 任务和目标 股票预测的主要任务和…...
UNiapp 微信小程序渐变不生效
开始用的一直是这个,调试一直没问题,但是重新启动就没生效,经查询这个不适合小程序使用:不适合没生效 background-image:linear-gradient(to right, #33f38d8a,#6dd5ed00); 正确使用下面这个: 生效,适合…...
FinClip 率先入驻 AWS Marketplace,加速全球市场布局
近日,凡泰极客旗下的小程序数字管理平台 FinClip 已成功上线亚马逊云科技(AWS)Marketplace。未来,FinClip 将主要服务于海外市场的开放银行、超级钱包、财富管理、社交电商、智慧城市解决方案等领域。 在全球市场的多样性需求推动…...
ChatGPT对话:Windows如何将Python训练模型转换为TensorFlow.js格式
【编者按】编者目前正在做手机上的人工智能软件,第一次做这种工作,从一些基本工作开始与ChatGPT交流。对初学者应该有帮助。 一天后修改文章补充内容: 解决TensorFlow 2.X与TensorFlow Decision Forests版本冲突问题: 在使用tens…...
封装网络请求 鸿蒙APP HarmonyOS ArkTS
一、效果展示 通过在页面直接调用 userLogin(params) 方法,获取登录令牌 二、申请网络权限 访问网络时候首先需要申请网络权限,需要修改 src/main 目录下的 module.json5 文件,加入 requestPermissions 属性,详见官方文档 【声明权…...
2024年度上半年中国汽车保值率报告
来源:中国汽车流通协会&精真估 近期历史回顾: 2024上半年房地产企业数智化转型报告.pdf 2024国产院线电影路演数据洞察报告.pdf 空间数据智能大模型研究-2024年中国空间数据智能战略发展白皮书.pdf 2024年全球资产管理报告 2024年中型律师事务所的法…...
Go语言之内存分配
文章收录在网站:http://hardyfish.top/ 文章收录在网站:http://hardyfish.top/ 文章收录在网站:http://hardyfish.top/ 文章收录在网站:http://hardyfish.top/ Go 语言程序所管理的虚拟内存空间会被分为两部分:堆内…...
北京交通大学《深度学习》专业课,实验3卷积、空洞卷积、残差神经网络实验
一、实验要求 1. 二维卷积实验(平台课与专业课要求相同) ⚫ 手写二维卷积的实现,并在至少一个数据集上进行实验,从训练时间、预测精 度、Loss变化等角度分析实验结果(最好使用图表展示) ⚫ 使用torch.nn…...
WPF中UI元素继承关系
在 WPF(Windows Presentation Foundation)框架中,UI 元素是基于一个层次化的类结构构建的,这个结构以 FrameworkElement 类为核心,大多数 UI 元素都是 FrameworkElement 或其派生类的子类。FrameworkElement 类本身又继…...
qml 实现一个listview
主要通过qml实现listvie功能,主要包括右键菜单,滚动条,拖动改变内容等,c 与 qml之间的变量和函数的调用。 main.cpp #include <QQuickItem> #include <QQmlContext> #include "testlistmodel.h" int main…...
【Leetcode】十六、深度优先搜索 宽度优先搜索 :二叉树的层序遍历
文章目录 1、深度优先搜索算法2、宽度优先搜索算法3、leetcode102:二叉树的层序遍历4、leetcode107:二叉树的层序遍历II5、leetcode938:二叉搜索树的范围和 1、深度优先搜索算法 深度优先搜索,即DFS,从root节点开始&a…...
Ruby教程
Ruby是一种动态的、面向对象的、解释型的脚本语言,以其简洁和易读性而闻名。Ruby的设计哲学强调程序员的生产力和代码的可读性,同时也融合了功能性和面向对象编程的特性。 以下是一个基础的Ruby教程,涵盖了一些基本概念和语法: …...
react + pro-components + ts完成单文件上传和批量上传
上传部分使用的是antd中的Upload组件,具体如下: GradingFilingReportUpload方法是后端已经做好文件流,前端只需要调用接口即可 单文件上传 <Uploadkey{upload_${record.id}}showUploadList{false}accept".xlsx"maxCount{1}customRequest{({ file }) > {const …...
暑假第一周——ZARA仿写
iOS学习 前言首页:无限轮播图商城:分类我的:自定义cell总结 前言 结束了UI的基础学习,现在综合运用开始写第一个demo,在实践中提升。 首页:无限轮播图 先给出效果: 无限轮播图,顾…...
github.com/antchfx/jsonquery基本使用
要在 GitHub 上使用 antchfx/jsonquery 库来查找 JSON 文档中的元素,首先需要了解这个库的基本用法。jsonquery 是一个用于查询 JSON 数据的 Go 语言库,允许使用 XPath 表达式来查找和选择 JSON 数据中的元素。 以下是一些基本步骤和示例,演…...
【python虚拟环境管理】【mac m3】使用poetry管理python项目
文章目录 一. 为什么选择poetry二. poetry相关操作1. 创建并激活环境2. 依赖包管理2.1. 安装项目依赖1.2. 管理不同开发环境的依赖1.3. 依赖维护1.4. 项目相关 Poetry是Python中用于依赖管理和打包的工具。它允许您声明项目所依赖的库,并将为您管理(安装…...
《JavaSE》---16.<抽象类接口Object类>
目录 前言 一、抽象类 1.1什么是抽象类 1.2抽象类代码实现 1.3 抽象类特点 1.4抽象类的作用 二、接口 2.1什么是接口 2.2接口的代码书写 2.3 接口使用 2.4 接口特点 2.5 实现多个接口 快捷键(ctrl i ): 2.6接口的好处 2.7 接…...
简单修改,让UE4/5着色器编译速度变快
简单修改,让UE4/5着色器编译速度变快 目录 简单修改,让UE4/5着色器编译速度变快 一、问题描述 二、解决方法 (一)硬件升级 (二)调整相关设置和提升优先级 1.调整相关设置 (1)…...
抖音去水印免费版哪个好用?2026实测推荐与软件对比
抖音去水印免费版哪个好用?2026实测推荐与软件对比 刷到一条有意思的视频想保存下来发给朋友,下载后却发现左上角顶着一串"用户名"水印;好不容易找到一段适合做素材的内容,画面边缘那行字怎么裁都裁不干净。这几乎是每个…...
5分钟掌握暗黑2存档编辑:免费开源工具d2s-editor完全指南
5分钟掌握暗黑2存档编辑:免费开源工具d2s-editor完全指南 【免费下载链接】d2s-editor 项目地址: https://gitcode.com/gh_mirrors/d2/d2s-editor 还在为暗黑破坏神2重复刷装备而烦恼?想快速体验不同职业Build却不想从头练级?今天我要…...
图灵完备8051 第三天 累加器A和寄存器B
如果EN_B1,则写入新数据,否则保持原状。EN_B_OUT1,则输出,否则高阻态A也一样...
Ubuntu服务器性能检测工具NetData安装
1. NetData安装 打开Ubuntu终端并输入以下指令: $ bash <(curl -Ss https://my-netdata.io/kickstart-static64.sh)中途会提示安装文件将为占用磁盘空间,是否继续(Y/N),输入Y即可,安装完成后的截图如下…...
通过Taotoken CLI工具一键配置团队开发环境与统一API密钥
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 通过Taotoken CLI工具一键配置团队开发环境与统一API密钥 基础教程类,介绍如何利用Taotoken提供的命令行工具ÿ…...
Anthropic Claude Haiku 4.5 安全突破:勒索行为从96%降至0%
上一篇: Google I/O 2026前瞻:Gemini 4.0、Android XR与AI原生生态的全面突破 下一篇: Anthropic ARR突破440亿美元:Q1营收同比增长80倍深度分析 核心结论: Anthropic通过"困难建议数据集"和宪法训练方法,成功将Claude模型的勒索行…...
【Oracle数据库指南】第32篇:Oracle归档日志管理与LogMiner日志分析
上一篇【第31篇】Oracle重做日志文件管理操作详解 下一篇【第33篇】Oracle表管理与分区表详解 摘要 归档日志(Archive Log)是Oracle数据库实现时间点恢复的核心机制,也是数据库备份恢复策略的重要组成部分。本文详细讲解归档模式的开启与配置…...
从收音机到5G:OFDM技术的前世今生,以及它为何成为Wi-Fi和5GNR的基石
从收音机到5G:OFDM技术的前世今生,以及它为何成为Wi-Fi和5GNR的基石 想象一下,你正用手机流畅播放4K视频,同时下载大文件——这背后是一套诞生于上世纪60年代的技术在支撑。OFDM(正交频分复用)的传奇之处在…...
长期使用Token Plan套餐在Taotoken平台带来的月度成本控制体验
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 长期使用Token Plan套餐在Taotoken平台带来的月度成本控制体验 对于个人开发者或小型团队而言,在探索和集成大模型能力…...
别再死记硬背了!用Python和NumPy从零实现5大激活函数(附梯度消失/爆炸分析)
用Python和NumPy实战五大激活函数:从公式推导到梯度问题深度解析 在深度学习的世界里,激活函数如同神经元的"开关",决定了信息能否在网络中流动。很多初学者面对教科书上抽象的数学公式时,常常陷入死记硬背的困境。本文…...
