图的拓扑排序
图的拓扑排序(Topological Sorting)是一种线性排序,用于有向无环图(Directed Acyclic Graph,DAG)。拓扑排序将图中的顶点排成一个线性序列,使得对于每一条有向边 (u, v),顶点 u 都排在顶点 v 之前。常见的拓扑排序算法有 Kahn 算法和基于深度优先搜索(DFS)的算法。
1. Kahn 算法
Kahn 算法是一种基于入度的贪心算法,逐步选择入度为 0 的顶点并移除其出边。
步骤:
- 计算每个顶点的入度。
- 初始化一个队列,将所有入度为 0 的顶点入队。
- 重复以下步骤,直到队列为空:
- 从队列中取出一个顶点,将其添加到拓扑排序结果中。
- 对该顶点的每条出边,将目标顶点的入度减 1。如果目标顶点的入度变为 0,则将其入队。
- 如果结果中的顶点数与图中的顶点数相等,则拓扑排序成功,否则图中存在环。
Java实现:
import java.util.*;public class KahnTopologicalSort {static class Graph {int V;List<Integer>[] adjacencyList;Graph(int V) {this.V = V;adjacencyList = new LinkedList[V];for (int i = 0; i < V; i++) {adjacencyList[i] = new LinkedList<>();}}void addEdge(int src, int dest) {adjacencyList[src].add(dest);}List<Integer> topologicalSort() {int[] inDegree = new int[V];for (int i = 0; i < V; i++) {for (int neighbor : adjacencyList[i]) {inDegree[neighbor]++;}}Queue<Integer> queue = new LinkedList<>();for (int i = 0; i < V; i++) {if (inDegree[i] == 0) {queue.add(i);}}List<Integer> topoOrder = new ArrayList<>();while (!queue.isEmpty()) {int u = queue.poll();topoOrder.add(u);for (int neighbor : adjacencyList[u]) {inDegree[neighbor]--;if (inDegree[neighbor] == 0) {queue.add(neighbor);}}}if (topoOrder.size() != V) {throw new RuntimeException("The graph has at least one cycle");}return topoOrder;}}public static void main(String[] args) {Graph graph = new Graph(6);graph.addEdge(5, 2);graph.addEdge(5, 0);graph.addEdge(4, 0);graph.addEdge(4, 1);graph.addEdge(2, 3);graph.addEdge(3, 1);List<Integer> topoOrder = graph.topologicalSort();System.out.println("Topological Sort: " + topoOrder);}
}
2. 基于深度优先搜索的拓扑排序
DFS 算法通过递归访问顶点,确保每个顶点在所有邻居顶点之后加入结果列表。
步骤:
- 初始化一个布尔数组,标记每个顶点是否被访问。
- 初始化一个栈,用于存储拓扑排序结果。
- 对每个顶点执行以下步骤(如果尚未被访问):
- 从该顶点开始进行 DFS。
- 在 DFS 过程中,将当前顶点标记为已访问,并递归访问所有未被访问的邻居顶点。
- DFS 完成后,将当前顶点压入栈。
- 从栈顶依次弹出顶点,形成拓扑排序结果。
Java实现:
import java.util.*;public class DFSTopologicalSort {static class Graph {int V;List<Integer>[] adjacencyList;Graph(int V) {this.V = V;adjacencyList = new LinkedList[V];for (int i = 0; i < V; i++) {adjacencyList[i] = new LinkedList<>();}}void addEdge(int src, int dest) {adjacencyList[src].add(dest);}void topologicalSortUtil(int v, boolean[] visited, Stack<Integer> stack) {visited[v] = true;for (int neighbor : adjacencyList[v]) {if (!visited[neighbor]) {topologicalSortUtil(neighbor, visited, stack);}}stack.push(v);}List<Integer> topologicalSort() {Stack<Integer> stack = new Stack<>();boolean[] visited = new boolean[V];for (int i = 0; i < V; i++) {if (!visited[i]) {topologicalSortUtil(i, visited, stack);}}List<Integer> topoOrder = new ArrayList<>();while (!stack.isEmpty()) {topoOrder.add(stack.pop());}return topoOrder;}}public static void main(String[] args) {Graph graph = new Graph(6);graph.addEdge(5, 2);graph.addEdge(5, 0);graph.addEdge(4, 0);graph.addEdge(4, 1);graph.addEdge(2, 3);graph.addEdge(3, 1);List<Integer> topoOrder = graph.topologicalSort();System.out.println("Topological Sort: " + topoOrder);}
}
结论
- Kahn算法:通过计算入度并逐步移除入度为 0 的顶点来实现拓扑排序。适用于在线性时间内完成排序,但需要额外的空间来存储入度。
- DFS算法:通过递归访问顶点来实现拓扑排序。适用于递归解决问题的场景,但需要维护递归栈和结果栈。
相关文章:
图的拓扑排序
图的拓扑排序(Topological Sorting)是一种线性排序,用于有向无环图(Directed Acyclic Graph,DAG)。拓扑排序将图中的顶点排成一个线性序列,使得对于每一条有向边 (u, v),顶点 u 都排…...
windows USB 设备驱动开发-总章
通用串行总线 (USB) 提供可扩展的即插即用串行接口,确保外围设备的标准、低成本的连接。 USB 设备包括键盘、鼠标、游戏杆、打印机、扫描仪、存储设备、调制解调器、视频会议摄像头等。USB-IF 是一个特别兴趣组 (SIG),负责维护官方 USB 规范、测试规范和…...
springboot解析自定义yml文件
背景 公司产品微服务架构下有十几个模块,几乎大部分模块都要连接redis。每次在客户那里部署应用,都要改十几遍配置,太痛苦了。当然可以用nacos配置中心的功能,配置公共参数。不过我是喜欢在应用级别上解决问题,因为并不…...
【C/C++】静态函数调用类中成员函数方法 -- 最快捷之一
背景 注册回调函数中,回调函数是一个静态函数。需要调用类对象中的一个成员函数进行后续通知逻辑。 方案 定义全局指针,用于指向类对象this指针 static void *s_this_obj;类构造函数中,将全局指针指向所需类的this指针 s_this_obj this…...
佣金的定义和类型
1. 佣金的定义 基本定义:佣金是指在商业交易中,代理人或中介机构为促成交易所获得的报酬。它通常是按交易金额的一定比例计算和支付的。支付方式:佣金可以是固定金额,也可以是交易金额的百分比。 2. 佣金的类型 销售佣金&#…...
python数据分析实训任务二(‘风力风向’)
import numpy as np import matplotlib.pyplot as plt # 数据 labelsnp.array([东风, 东北风, 北风, 西北风, 西风, 西南风, 南风, 东南风]) statsnp.array([2.1, 2, 0, 3, 1.5, 3, 6, 4]) # 将角度转换为弧度 anglesnp.linspace(0, 2*np.pi, len(labels), endpointFalse).toli…...
Java技术栈总结:数据库MySQL篇
一、慢查询 1、常见情形 聚合查询 多表查询 表数据量过大查询 深度分页查询 2、定位慢查询 方案一、开源工具 调试工具:Arthas运维工具:Prometheus、Skywalking 方案二、MySQL自带慢日志 在MySQL配置文件 /etc/my.conf 中配置: # …...
vue-cli 项目打包优化-基础篇
1、项目打包完运行空白 引用资源路径问题,打包完的【index.html】文件引用其他文件的引用地址不对 参考配置:https://cli.vuejs.org/zh/config 修改vue.config.js ,根据与 后端 或 运维 沟通修改 module.export {// 默认 publicPath: //…...
24/06/26(1.1129)动态内存
strtok 字符串分割函数 #include<stdio.h> int main(){ char str[] "this,a sample string."; char* sep ","; char* pch strtok(str, sep); printf("%s\n", pch); while (pch ! NULL){ printf("%s\…...
基于 elementUI / elementUI plus,实现 主要色(主题色)的一件换色(换肤)
一、效果图 二、方法 改变elementUI 的主要色 --el-color-primary 为自己选择的颜色,核心代码如下: // 处理主题样式 export function handleThemeStyle(theme) {document.documentElement.style.setProperty(--el-color-primary, theme) } 三、全部代…...
js 计算某个日期加月份最后月份不会增加或者跳变
/** * * param {*} dateString 原来日期 2023-12-31 * param {*} months 加月份 2 * returns 2024-02-29 */ export function getDateByMonth(dateString, months0) { console.log(1); let oldMonths dateString.substring(0,7); let day dateString.substring(8); let …...
Git简介与详细教程
一、简介 什么是Git? Git是一款分布式版本控制系统,由Linux之父Linus Torvalds于2005年开发。它旨在快速、高效地处理从小型到大型项目的所有内容。Git与传统的版本控制系统相比,具备显著的优势,主要体现在其分布式架构、强大的…...
创建OpenWRT虚拟机
环境:Ubuntu 2204,VM VirtualBox 7.0.18 安装必备软件包: sudo apt update sudo apt install subversion automake make cmake uuid-dev gcc vim build-essential clang flex bison g gawk gcc-multilib g-multilib gettext git libncurses…...
智慧安防新篇章:如何科学设定可燃气体报警器校准检测周期
随着科技的快速发展,智慧安防系统已成为现代社会不可或缺的一部分。在各类安全监测设备中,可燃气体报警器因其对潜在危险的及时预警功能而备受关注。 接下来,佰德将围绕可燃气体报警器的校准检测周期进行深入探讨,以确保其在智慧…...
如何优化Spring Boot应用的启动时间
如何优化Spring Boot应用的启动时间 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们将讨论如何优化Spring Boot应用的启动时间,提升应用的性…...
(Effective C) 2.3 作用域
(Effective C) 2.3 作用域 文章目录 (Effective C) 2.3 作用域前言🔢4大作用域1️⃣文件作用域2️⃣块作用域3️⃣函数原型作用域4️⃣函数作用域 ⭐作用域性质📖实例CodeEND关注我 前言 作用域应用于标识符的某个特定声明。 标识符包含对象࿰…...
Python 基础 (标准库):堆 heap
1. 官方文档 heapq --- 堆队列算法 — Python 3.12.4 文档 2. 相关概念 堆 heap 是一种具体的数据结构(concrete data structures);优先级队列 priority queue 是一种抽象的数据结构(abstract data structures)&…...
动手学深度学习(Pytorch版)代码实践 -卷积神经网络-30Kaggle竞赛:图片分类
30Kaggle竞赛:图片分类 比赛链接: https://www.kaggle.com/c/classify-leaves 导入包 import torch import torchvision from torch.utils.data import Dataset, DataLoader from torchvision import transforms import numpy as np import pandas as…...
【LeetCode】每日一题:数组中的第K大的元素
给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。 请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。 你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。 解题思路 第一种是快排,快…...
Keil5.38ARM,旧编译器(V5)安装
站内文章KEIL5MDK最新版(3.37)安装以及旧编译器(V5)安装_keil5 mdk-CSDN博客...
C++ 智能指针的底层实现逻辑
C智能指针的底层实现逻辑揭秘 在C开发中,内存管理一直是程序员需要谨慎处理的难题。传统裸指针容易导致内存泄漏、悬垂指针等问题,而智能指针通过自动化资源管理,显著提升了代码的安全性和可维护性。那么,智能指针是如何在底层实…...
第4章 编码规范-4.1 命名规范
在Python中,变量、常量、模块、包、函数、类、对象、属性、方法和异常类都具有一定的命名规范。但是,这些命名规范都是通用性规范,而不是强制性规范,所以具体的命名规范还需要以开发项目的要求为主。(1)变量…...
免环境配置:Qwen-Image定制镜像让4090D显卡快速跑通视觉语言模型
免环境配置:Qwen-Image定制镜像让4090D显卡快速跑通视觉语言模型 1. 引言 1.1 视觉语言模型的应用价值 在当今AI技术快速发展的背景下,视觉语言模型(VLM)已成为连接计算机视觉与自然语言处理的桥梁。这类模型能够理解图像内容并生成相关文本描述&…...
春联生成模型-中文-base多线程批量生成教程,为公司百名员工定制春节祝福
春联生成模型-中文-base多线程批量生成教程,为公司百名员工定制春节祝福 春节将至,为公司员工准备个性化春联是传递祝福的好方式。传统手工创作耗时耗力,而春联生成模型-中文-base结合多线程技术,能高效完成批量定制。本文将详细…...
探索AI原生应用领域向量数据库的无限潜力
探索AI原生应用领域向量数据库的无限潜力关键词:向量数据库、AI原生应用、Embedding、向量相似度、多模态检索、大模型协同、语义理解摘要:当AI从“辅助工具”进化为“原生生产力”,一种专为AI设计的数据库——向量数据库,正在重塑…...
【嵌入式Linux】Libmodbus RTU从源码到实战:基于i.MX6UL的工业通信移植指南
1. 为什么选择Libmodbus RTU在i.MX6UL上做工业通信? 在工业自动化领域,Modbus协议就像设备之间的"普通话",而RTU模式则是其中最省流量、最抗干扰的方言。我去年给一家工厂做设备改造时,发现他们的老式PLC和传感器清一色…...
【架构实战】分布式事务解决方案
一、分布式事务的挑战 在微服务架构下,一个业务操作可能涉及多个服务的数据修改。传统的本地事务无法保证跨服务的数据一致性。 经典场景: 用户下单 → 订单服务扣库存 → 支付服务扣余额 → 物流服务创建运单任何一步失败,都需要回滚之前的操…...
手把手教你用RTABMAP+T265在Windows10上实现室内三维扫描(含标定技巧)
手把手教你用RTABMAPT265在Windows10上实现高精度室内三维扫描 第一次接触室内三维扫描时,我被这项技术深深吸引——它能让物理空间瞬间数字化,就像给现实世界按下"CtrlC"。但真正动手配置RTABMAP和T265相机时,才发现这条路并不平坦…...
AI 开发实战:给团队定一套能落地的 AI 使用规范
AI 开发实战:给团队定一套能落地的 AI 使用规范 一、为什么团队用了 AI 反而容易更乱? 因为每个人都在各自试: 有人用来写代码有人用来写文档有人用来查错有人输出直接复制上线 如果没有基本规范,效率可能提升了,但风险…...
比亚迪多款新车激光雷达性能超越华为:千线级感知开启智驾新纪元
2026年,中国智能驾驶行业正式进入“千线级激光雷达”时代。继华为发布896线双光路激光雷达后,比亚迪携速腾聚创EM4数字化激光雷达强势反击,以1080线物理扫描、600米最远探测的硬核参数,在核心感知硬件上实现对华为的全面超越。这一突破不仅标志着比亚迪补齐了智能化短板,更…...
