代码随想录算法训练营Day64|拓扑排序(卡码网117)、dijkstra朴素版
拓扑排序
117. 软件构建 (kamacoder.com)
拓扑排序简单的说是将一个有向图转为线性的排序。
它将图中的所有结点排序成一个线性序列,使得对于任何的边uv,结点u在序列中都出现在结点v之前,这样的序列满足图中所有的前驱-后继关系。
拓扑排序通常用于任务调度、项目计划、编译依赖分析等场景,其中活动或任务之间存在依赖关系,需要确定一个合理的执行顺序。
拓扑排序的算法步骤如下:
- 选择一个没有前驱的结点(即入度为0的结点),将其加入到拓扑排序的序列中,并从图中删除该节点及其所有出边。
- 重复步骤1,直到所有的结点都被加入拓扑排序序列中或者途中不再存在无前驱的结点。
- 如果所有的结点都被加入序列中,则完成了拓扑排序;若图中还存在结点,则说明图中存在环,无法进行拓扑排序。
由于拓扑排序的结果可能不唯一,当图中存在多个入度为0的结点,可以任意选择一个结点进行删除。
在实际应用中,拓扑排序通常和深度优先搜索或广度优先搜素结合使用。例如,使用广度优先搜索(拓扑排序的广度优先搜索实现通常被称为Kahn算法)进行拓扑排序的算法流程如下:
-
计算所有节点的入度:遍历图中的所有节点,计算每个节点的入度(即有多少边指向该节点)。
-
初始化队列:创建一个空队列,将所有入度为0的节点加入队列。这些节点是没有前置依赖的节点,可以开始执行。
-
处理队列:只要队列不为空,就重复以下步骤:
- 从队列中取出一个节点(称为当前节点),并将其添加到拓扑排序的结果序列中。
- 减少当前节点的所有出边指向的节点的入度(因为这些节点的依赖减少了)。
- 如果某个节点的入度在减少后变为0,则将其加入队列,因为它现在没有前置依赖了。
-
检查是否有未处理的节点:当队列为空时,如果所有的节点都已经添加到拓扑排序的结果序列中,则拓扑排序成功完成。如果还有节点未添加到结果序列中,则说明图中存在环,因此无法进行拓扑排序。
伪代码
拓扑排序(图 G):初始化入度为0的队列 Q初始化拓扑排序的结果序列 L// 计算所有节点的入度对于每个节点 v in G:v.入度 = G 中指向 v 的边的数量如果 v.入度 == 0:Q.enqueue(v)// 处理队列当 Q 不为空时:当前节点 u = Q.dequeue()L.add(u) // 将 u 添加到拓扑排序的结果序列中// 减少所有出边的目标节点的入度对于每个节点 v,其中存在边 u -> v:v.入度 = v.入度 - 1如果 v.入度 == 0:Q.enqueue(v)// 检查是否所有节点都已处理如果 L 中的节点数量不等于 G 中的节点数量:返回 "图 G 包含环,无法进行拓扑排序"否则:返回 L 作为拓扑排序的结果序列
C++代码参考代码随想录代码随想录 (programmercarl.com)
#include <iostream>
#include <vector>
#include <queue>
#include <unordered_map>
using namespace std;int main() {int N, M; // N个文件存在M条依赖关系cin >> N >> M;vector<int> inDegree(N, 0); // 记录每个点的入度unordered_map<int, vector<int>> umap;// 读取M条依赖关系for (int i = 0; i < M; i++) {int s, t;cin >> s >> t;// t依赖于s,因此t的入度加1inDegree[t]++;umap[s].push_back(t);}queue<int> Queue;// 将所有入度为0的节点加入队列for (int i = 0; i < N; i++) {if (inDegree[i] == 0)Queue.push(i);}vector<int> path; // 存储拓扑排序结果while (!Queue.empty()) {int cur = Queue.front();Queue.pop();path.push_back(cur);// 遍历当前节点的所有后继节点for (int next : umap[cur]) {inDegree[next]--;if (inDegree[next] == 0)Queue.push(next);}}// 检查是否所有的节点都被处理了if (path.size() == N) {for (int i = 0; i < N - 1; i++) {cout << path[i] << " ";}cout << path[N - 1];} else {// 如果不是所有的节点都被处理,说明存在环cout << -1 << endl;}return 0;
}
在时间复杂度上,初始化入度数组O(N),读取依赖关系并构建邻接表O(M)(M条依赖关系),将入度为0结点加入队列,O(N),BFS的时间复杂度为O(N+M)(每个结点最多访问一次,每个结点被加入队列后移除,每条边会被访问一次来减少相邻结点的入度)时间复杂度为O(N+M)
空间复杂度 入度数组O(N),邻接表最差情况下O(N^2),队列和路径数组都为O(N),最差情况下空间复杂度为O(N^2),但实际应用中,若图比较稀疏,则空间复杂度为O(M+N)。
dijkstra
47. 参加科学大会(第六期模拟笔试) (kamacoder.com)
Dijkatra算法是一种著名的图搜索算法,它用于在加权图中找到从一源节点到其余所有结点的最短路径。
算法步骤:
- 初始化:需要一个最短路径估计的容器(优先队列,通常是最小堆)存储所有结点及其当前的最短路径估计值,除源节点设置为0外,将所有结点的最短路径估计值设置为无穷大。
- 访问源结点:将源结点加入优先队列。
- 循环处理队列:当优先队列非空时,重复以下步骤:
从优先队列中取出具有最小估计值的节点,称为当前节点。
对于当前节点的每个邻接节点,执行以下操作:
- 计算通过当前节点到达邻接节点的路径长度。
- 如果这个路径长度比已知的最短路径估计值更短,则更新邻接节点的最短路径估计值,并更新它的前驱节点为当前节点。
- 将邻接节点及其新的最短路径估计值加入优先队列。
- 标记完成:当一个结点从优先队列取出时,意味着它的最短路径已经确定,可以将其标记为完成。
- 构建最短路径树:当算法结束时,可以从源结点开始,通过每个结点的前驱结点信息,构造出从源结点到所有其他结点的最短路径树。
需要注意的几个点:
- Dijkstra算法不能处理带有负权边的图,因为在有负权边的图中,可能存在一条路径,其总权重随着经过的边数增加而减少,导致无法正确找到最短路径。
- Dijkstra算法的时间复杂度为O(V^2),V为图中结点的数量,使用优先队列可以优化到O(E+VlogV),E为边的数量、
- Dijkstra可以用于有向图和无向图。
代码随想录 (programmercarl.com)
#include <iostream>
#include <vector>
#include <climits>
using namespace std;int main() {int N, M; // N个文件存在M条依赖关系cin >> N >> M;vector<vector<int>> grid(N+1, vector<int>(N+1, INT_MAX)); // 创建一个N+1xN+1的二维数组,用于存储节点之间的权重,初始化为INT_MAXint v1, v2, val;for (int i = 0; i < M; i++) { // 读取M条依赖关系cin >> v1 >> v2 >> val; // 读取两个节点v1和v2以及它们之间的权重valgrid[v1][v2] = val; // 更新权重矩阵,表示v1到v2有边,权重为val}int start = 1; // 定义起始节点为1int end = N; // 定义目标节点为Nvector<int> minDist(N+1, INT_MAX); // 创建一个长度为N+1的数组,用于存储从起始节点到其他节点的最短路径估计值,初始化为INT_MAXvector<int> visited(N+1, 0); // 创建一个长度为N+1的数组,用于标记节点是否被访问过,0表示未访问,1表示已访问minDist[start] = 0; // 起始节点到自身的最短路径为0for (int i = 0; i <= N; i++) { // 循环,找到未访问的最短路径节点int minVal = INT_MAX; // 初始化最小值为INT_MAXint cur = 1; // 初始化当前节点为1for (int v = 1; v <= N; v++) { // 遍历所有节点,找到未访问且最短路径估计值最小的节点if (!visited[v] && minDist[v] < minVal) { // 如果节点v未访问且最短路径估计值小于minValminVal = minDist[v]; // 更新最小值cur = v; // 更新当前节点为v}}visited[cur] = 1; // 标记当前节点为已访问for (int v = 1; v <= N; v++) { // 遍历所有节点,更新从当前节点出发到其他节点的最短路径估计值if (!visited[v] && grid[cur][v] != INT_MAX && minDist[cur] + grid[cur][v] < minDist[v]) {// 如果节点v未访问,且当前节点到节点v有边,且通过当前节点到达v的路径更短minDist[v] = minDist[cur] + grid[cur][v]; // 更新节点v的最短路径估计值}}}if (minDist[end] == INT_MAX) // 如果目标节点的最短路径估计值仍然是INT_MAX,表示没有路径到达目标节点cout << -1 << endl; // 输出-1elsecout << minDist[end] << endl; // 否则输出从起始节点到目标节点的最短路径长度return 0;
}
算法的时间复杂度为O(N^2),空间复杂度这里也是O(N^2)(没有用上最小堆等优先队列)
相关文章:
代码随想录算法训练营Day64|拓扑排序(卡码网117)、dijkstra朴素版
拓扑排序 117. 软件构建 (kamacoder.com) 拓扑排序简单的说是将一个有向图转为线性的排序。 它将图中的所有结点排序成一个线性序列,使得对于任何的边uv,结点u在序列中都出现在结点v之前,这样的序列满足图中所有的前驱-后继关系。 拓扑排…...
neo4j 图数据库:Cypher 查询语言、医学知识图谱
neo4j 图数据库:Cypher 查询语言、医学知识图谱 Cypher 查询语言创建数据查询数据查询并返回所有节点查询并返回所有带有特定标签的节点查询特定属性的节点及其所有关系和关系的另一端节点查询从名为“小明”的节点到名为“小红”的节点的路径 更新数据更新一个节点…...
数据结构基础--------【二叉树基础】
二叉树基础 二叉树是一种常见的数据结构,由节点组成,每个节点最多有两个子节点,左子节点和右子节点。二叉树可以用来表示许多实际问题,如计算机程序中的表达式、组织结构等。以下是一些二叉树的概念: 二叉树的深度&a…...
数据开源 | Magic Data大模型高质量十万轮对话数据集
能够自然的与人类进行聊天交谈,是现今的大语言模型 (LLM) 区别于传统语言模型的重要能力之一,近日OpenAI推出的GPT-4o给我们展示了这样的可能性。 对话于人类来说是与生俱来的,但构建具备对话能力的大模型是一项不小的挑战,收集高…...
webpack之ts打包
tsconfig.json配置 // 是否对js文件进行编译,默认false"allowJs": true,// 是否检查js代码是否符合语法规范,默认false(引入的外部文件有可能语法有问题)"checkJs": true, allowJs和checkJs基本是同时出现,因为有了allowJs 这个检查…...
MATLAB数据统计描述和分析
描述性统计就是搜集、整理、加工和分析统计数据, 使之系统化、条理化,以显示出数据资料的趋势、特征和数量关系。它是统计推断的基础,实用性较强,在数学建模的数据描述部分经常使用。 目录 1.频数表和直方图 2 .统计量 3.统计…...
设计分享—国外后台界面设计赏析
国外后台界面设计将用户体验放在首位,通过直观易懂的布局和高效的交互设计,提升用户操作效率和满意度。 设计不仅追求美观大方,还注重功能的实用性和数据的有效展示,通过图表和图形化手段使数据更加直观易懂。 采用响应式布局&a…...
最小生成树(算法篇)
算法之最小生成树 最小生成树 概念: 最小生成树是一颗连接图G所有顶点的边构成的一颗权最小的树,最小生成树一般是在无向图中寻找。最小生成树共有N-1条边(N为顶点数)。 算法: Prim算法 概念: Prim(普里姆)算法是生成最小生…...
教师管理小程序的设计
管理员账户功能包括:系统首页,个人中心,教师管理,个人认证管理,课程信息管理,课堂记录管理,课堂统计管理,留言板管理 微信端账号功能包括:系统首页,课程信息…...
Selenium 等待
环境: Python 3.8 selenium3.141.0 urllib31.26.19 Chromium 109.0.5405.0 (32 位) # 1 固定等待(time) # 固定待是利用python语言自带的time库中的sleep()方法,固定等待几秒。 # 这种方式会导致这个脚本运…...
安装easy-handeye
一、aruco_ros配置 mkdir -p ~/ros_ws/src cd ~/ros_ws/src git clone -b melodic-devel https://github.com/pal-robotics/aruco_ros.git cd .. catkin_make 二、visp配置(需要联外网下载东西,不然会一直出问题) sudo apt-get install ros-melodic-…...
【面试题】MySQL 索引(第二篇)
1.索引 索引是数据库中的一个核心概念,它对于提高数据库查询效率至关重要。以下是索引的详细概念解析: 一、索引的定义 基本定义:索引是一个排序的列表,其中存储着索引的值和包含这些值的数据所在行的物理地址(或逻…...
4. 小迪安全v2023笔记 javaEE应用
4. 小迪安全v2023笔记 javaEE应用 大体上跟随小迪安全的课程,本意是记录自己的学习历程,不能说是完全原创吧,大家可以关注一下小迪安全。 若有冒犯,麻烦私信移除。 默认有java基础。 文章目录 4. 小迪安全v2023笔记 javaEE应…...
anaconda修改安装的默认环境
📚博客主页:knighthood2001 ✨公众号:认知up吧 (目前正在带领大家一起提升认知,感兴趣可以来围观一下) 🎃知识星球:【认知up吧|成长|副业】介绍 ❤️如遇文章付费,可先看…...
MySQL 9.0 正式发行Innovation创新版已支持向量
从 MySQL 8.1 开始,官方启用了新的版本模型:MySQL 创新版 (Innovation) 和长期支持版 (LTS)。 根据介绍,两者的质量都已达到可用于生产环境级别。区别在于: 如果希望尝试最新的功能和改进,并喜欢与最新技术保持同步&am…...
基于Java+SpringMvc+Vue技术的智慧校园系统设计与实现
博主介绍:硕士研究生,专注于信息化技术领域开发与管理,会使用java、标准c/c等开发语言,以及毕业项目实战✌ 从事基于java BS架构、CS架构、c/c 编程工作近16年,拥有近12年的管理工作经验,拥有较丰富的技术架…...
【蔬菜网元宇宙】—— 探索农业的未来之旅
在数字化时代的浪潮中,技术和创新不断塑造着我们的生活方式。现在,这种变革已经延伸到了农业领域。蔬菜网,一个专注于农产品供应链的领先平台,自豪地宣布我们正式迈入元宇宙的世界——一个全新的虚拟空间,旨在彻底改变…...
淘宝商品历史价格查询(免费)
当前资料来源于网络,禁止用于商用,仅限于学习。 淘宝联盟里面就可以看到历史价格 并且没有加密 淘宝商品历史价格查询可以通过以下步骤进行: 先下载后,登录app注册账户 打开淘宝网站或淘宝手机App。在搜索框中输入你想要查询的商…...
14-47 剑和诗人21 - 2024年如何打造AI创业公司
2024 年,随着人工智能继续快速发展并融入几乎所有行业,创建一家人工智能初创公司将带来巨大的机遇。然而,在吸引资金、招聘人才、开发专有技术以及将产品推向市场方面,人工智能初创公司也面临着相当大的挑战。 让我来…...
WPF界面设计-更改按钮样式 自定义字体图标
一、下载图标文件 iconfont-阿里巴巴矢量图标库 二、xaml界面代码编辑 文件结构  对应的图标代码 Fonts/#iconfont 对应文件位置 <Window.Resources><ControlTemplate TargetType"Button" x:Key"CloseButtonTemplate"…...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
论文笔记——相干体技术在裂缝预测中的应用研究
目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术:基于互相关的相干体技术(Correlation)第二代相干体技术:基于相似的相干体技术(Semblance)基于多道相似的相干体…...
代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...
FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...
