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

【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方法可以实现拓扑排序,广泛应用于任务调度、课程安排、编译依赖和数据处理等场景。理解和掌握拓扑排序算法,对于解决实际问题具有重要意义。


相关文章:

【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功能&#xff0c;主要包括右键菜单&#xff0c;滚动条&#xff0c;拖动改变内容等&#xff0c;c 与 qml之间的变量和函数的调用。 main.cpp #include <QQuickItem> #include <QQmlContext> #include "testlistmodel.h" int main…...

【Leetcode】十六、深度优先搜索 宽度优先搜索 :二叉树的层序遍历

文章目录 1、深度优先搜索算法2、宽度优先搜索算法3、leetcode102&#xff1a;二叉树的层序遍历4、leetcode107&#xff1a;二叉树的层序遍历II5、leetcode938&#xff1a;二叉搜索树的范围和 1、深度优先搜索算法 深度优先搜索&#xff0c;即DFS&#xff0c;从root节点开始&a…...

Ruby教程

Ruby是一种动态的、面向对象的、解释型的脚本语言&#xff0c;以其简洁和易读性而闻名。Ruby的设计哲学强调程序员的生产力和代码的可读性&#xff0c;同时也融合了功能性和面向对象编程的特性。 以下是一个基础的Ruby教程&#xff0c;涵盖了一些基本概念和语法&#xff1a; …...

react + pro-components + ts完成单文件上传和批量上传

上传部分使用的是antd中的Upload组件,具体如下: GradingFilingReportUpload方法是后端已经做好文件流,前端只需要调用接口即可 单文件上传 <Uploadkey{upload_${record.id}}showUploadList{false}accept".xlsx"maxCount{1}customRequest{({ file }) > {const …...

暑假第一周——ZARA仿写

iOS学习 前言首页&#xff1a;无限轮播图商城&#xff1a;分类我的&#xff1a;自定义cell总结 前言 结束了UI的基础学习&#xff0c;现在综合运用开始写第一个demo&#xff0c;在实践中提升。 首页&#xff1a;无限轮播图 先给出效果&#xff1a; 无限轮播图&#xff0c;顾…...

github.com/antchfx/jsonquery基本使用

要在 GitHub 上使用 antchfx/jsonquery 库来查找 JSON 文档中的元素&#xff0c;首先需要了解这个库的基本用法。jsonquery 是一个用于查询 JSON 数据的 Go 语言库&#xff0c;允许使用 XPath 表达式来查找和选择 JSON 数据中的元素。 以下是一些基本步骤和示例&#xff0c;演…...

【python虚拟环境管理】【mac m3】使用poetry管理python项目

文章目录 一. 为什么选择poetry二. poetry相关操作1. 创建并激活环境2. 依赖包管理2.1. 安装项目依赖1.2. 管理不同开发环境的依赖1.3. 依赖维护1.4. 项目相关 Poetry是Python中用于依赖管理和打包的工具。它允许您声明项目所依赖的库&#xff0c;并将为您管理&#xff08;安装…...

《JavaSE》---16.<抽象类接口Object类>

目录 前言 一、抽象类 1.1什么是抽象类 1.2抽象类代码实现 1.3 抽象类特点 1.4抽象类的作用 二、接口 2.1什么是接口 2.2接口的代码书写 2.3 接口使用 2.4 接口特点 2.5 实现多个接口 快捷键&#xff08;ctrl i &#xff09;&#xff1a; 2.6接口的好处 2.7 接…...

简单修改,让UE4/5着色器编译速度变快

简单修改&#xff0c;让UE4/5着色器编译速度变快 目录 简单修改&#xff0c;让UE4/5着色器编译速度变快 一、问题描述 二、解决方法 &#xff08;一&#xff09;硬件升级 &#xff08;二&#xff09;调整相关设置和提升优先级 1.调整相关设置 &#xff08;1&#xff09…...

如何查看极狐GitLab Helm Chart?

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab &#xff1a;https://gitlab.cn/install?channelcontent&utm_sourcecsdn 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署…...

代码随想录算法训练营第十六天| 530.二叉搜索树的最小绝对差、501.二叉搜索树中的众数、236. 二叉树的最近公共祖先

写代码的第十六天&#xff0c;自从到了二叉树错误版代码就少了&#xff0c;因为我自己根本没思路&#xff0c;都是看完思路在做&#xff0c;那基本上就是小语法问题&#xff0c;很少有其他问题了&#xff0c;证实了我好菜。。。。。。 还是得写思路啊啊啊啊&#xff0c;写思路好…...

NODEJS复习(ctfshow334-344)

NODEJS复习 web334 下载源码代码审计 发现账号密码 代码逻辑 var findUser function(name, password){ return users.find(function(item){ return name!CTFSHOW && item.username name.toUpperCase() && item.password password; }); }; 名字不等于ctf…...

【Go系列】RPC和grpc

承上启下 介绍完了Go怎么实现RESTFul api&#xff0c;不可避免的&#xff0c;今天必须得整一下rpc这个概念。rpc是什么呢&#xff0c;很多人都想把rpc和http一起对比&#xff0c;但是他们不是一个概念。RPC是一种思想&#xff0c;可以基于tcp&#xff0c;可以基于udp也可以基于…...

【VUE】v-if和v-for的优先级

v-if和v-for v-if 用来显示和隐藏元素 flag为true时&#xff0c;dom元素会被删除达到隐藏效果 <div class"boxIf" v-if"flag"></div>v-for用来进行遍历&#xff0c;可以遍历数字对象数组&#xff0c;会将整个元素遍历指定次数 <!-- 遍…...

【单目3D检测】smoke(1):模型方案详解

纵目发表的这篇单目3D目标检测论文不同于以往用2D预选框建立3D信息&#xff0c;而是采取直接回归3D信息&#xff0c;这种思路简单又高效&#xff0c;并不需要复杂的前后处理&#xff0c;而且是一种one stage方法&#xff0c;对于实际业务部署也很友好。 题目&#xff1a;SMOKE&…...

数据库系统概论:数据库系统的锁机制

引言 锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中&#xff0c;数据作为一种共享资源&#xff0c;其并发访问的一致性和有效性是数据库必须解决的问题。锁机制通过对数据库中的数据对象&#xff08;如表、行等&#xff09;进行加锁&#xff0c;以确保在同…...

Django+vue自动化测试平台(28)-- ADB获取设备信息

概述 adb的全称为Android Debug Bridge&#xff0c;就是起到调试桥的作用。通过adb可以在Eclipse中通过DDMS来调试Android程序&#xff0c;说白了就是调试工具。 adb的工作方式比较特殊&#xff0c;采用监听Socket TCP 5554等端口的方式让IDE和Qemu通讯&#xff0c;默认情况下…...

RESTful API设计指南:构建高效、可扩展和易用的API

文章目录 引言一、RESTful API概述1.1 什么是RESTful API1.2 RESTful API的重要性 二、RESTful API的基本原则2.1 资源导向设计2.2 HTTP方法的正确使用 三、URL设计3.1 使用名词而非动词3.2 使用复数形式表示资源集合 四、请求和响应设计4.1 HTTP状态码4.2 响应格式4.2.1 响应实…...

npm下载的依赖包版本号怎么看

npm下载的依赖包版本号怎么看 版本号一般分三个部分&#xff0c;主版本号、次版本号、补丁版本号。 主版本号&#xff1a;一般依赖包发生重大更新时&#xff0c;主版本号才回发生变化&#xff0c;如Vue2.x到Vue3.x。次版本号&#xff1a;当依赖包中发生了一些小变化&#xff…...

企业网站的建设过程/保定seo推广外包

class Solution:找到数组中结果与k接近的3个元素def threeSumClosest(self, numbers, target):# 排序numbers.sort()# 最接近的和ans None# 结果列表res []for i in range(len(numbers)):left, right i 1, len(numbers) - 1# 从i号位置开始搜索&#xff0c;i0时搜索右边所有…...

做网站用的hu软件/惠州seo计费

一、作用域 1、作用域问题&#xff1a;在一个函数中定义的变量&#xff0c;在其他函数中能否被引用&#xff1f;在不同位置定义的变量&#xff0c;在什么范围内有效&#xff1f; 2、定义变量可能有3种情况 [谭浩强] &#xff08;1&#xff09;在函数的开头定义&#xff1b; &am…...

做刀模网站/企业线上培训平台有哪些

原文链接&#xff1a;工程师男友如何反窃听&#xff1f;趣聊密码学入门科普 阿里妹导读&#xff1a;谁都不想在通信过程中被别人“窃取”小秘密。本文借助一对情侣与八卦女、猥琐男的斗智故事&#xff0c;为大家讲述科普密码学基础知识。既有料又有趣&#xff0c;深入浅出&…...

wordpress最新begin主题下载/会员制营销方案

文章目录商品列表页逻辑代码商品列表页的数据渲染商品详细页Ajax实现商品收藏商品列表页逻辑代码 commodity的views.py定义视图函数commodityView from django.core.paginator import Paginator, PageNotAnInteger,EmptyPage from django.http import HttpResponse from djan…...

wordpress整站安装/十大免费推广平台

摘要&#xff1a;图灵图灵细胞序列改变跳跃中能自身基因位置的一段D称为。转录模板基因一条链为A的是以&#xff0c;够模互补合成过程配对碱基原则按照A的。小的序列或者通过者完配对与靶抑制引起全地编码部分靶m的R地或A的、拟计难非分子翻译可以。...图灵图灵细胞序列改变跳跃…...

网站制作的软件有哪些/百度首页网站推广多少钱一年

一、冒泡排序 1、Explanation And Steps&#xff08;解释的步骤&#xff09; 冒泡排序&#xff08;Bubble Sort&#xff09;也是一种简单直观的排序算法。它重复地走访过要排序的数列&#xff0c;一次比较两个元素&#xff0c;如果他们的顺序错误就把他们交换过来。走访数列的…...