dfs_bool_void 两种写法感悟

dfs 的两种写法

在看之前实现图的遍历 dfs 和拓扑排序 dfs 实现的代码的时候的感悟

图的遍历 dfs 和拓扑排序 dfs 的区别

0 → 1
↓   ↓
2 → 3

图的邻接表表示:

adjList[0] = {1, 2};
adjList[1] = {3};
adjList[2] = {3};
adjList[3] = {};
  1. 正常的 DFS 遍历:

    从节点 0 开始执行 DFS,假设我们按照邻接表的顺序遍历:

    从节点 0 开始,访问 0,然后访问 0 的邻接节点 1 和 2

    从节点 1 开始,访问 1,然后访问 1 的邻接节点 3

    从节点 3 开始,访问 3,发现没有邻接节点

    回到节点 1,再回到节点 0,访问 2

    从节点 2 开始,访问 2,然后访问 2 的邻接节点 3(但 3 已经访问过了)

    DFS 遍历的顺序:0 -> 1 -> 3 -> 2

  2. 拓扑排序的 DFS 遍历:

    在拓扑排序中,我们使用栈存储节点,并确保先访问所有邻接节点再加入栈

    从节点 0 开始,访问 0,并标记为“正在访问”

    访问 0 的邻接节点 1,并标记为“正在访问”

    访问 1 的邻接节点 3,并标记为“正在访问”

    节点 3 没有邻接节点,标记为“已访问”,并将 3 放入栈中

    回到节点 1,标记为“已访问”,并将 1 放入栈中

    回到节点 0,访问 2,并标记为“正在访问”

    访问 2 的邻接节点 3(已访问过),因此直接标记 2 为“已访问”,并将 2 放入栈中

    回到节点 0,标记为“已访问”,并将 0 放入栈中

    拓扑排序的顺序:3 -> 1 -> 2 -> 0

总结两者的区别

DFS 遍历按照遇到的第一个未访问的邻接节点进行递归访问, 直接记录 节点的访问顺序

拓扑排序要求节点在加入结果时要等到其 所有邻接节点被完全访问 过,因此节点的加入顺序是倒序的(即后序遍历)

代码

原 dfs 遍历代码

void MyGraph::dfsVisit(int vertex, vector<bool>& visited, vector<int>& traversal) 
{visited[vertex] = true;traversal.push_back(vertex);for (const auto& edge : adjList[vertex])if (!visited[edge.first])dfsVisit(edge.first, visited, traversal); 
}void MyGraph::DFS(int startVertex) 
{vector<bool> visited(n, false); vector<int> traversal; dfsVisit(startVertex, visited, traversal);for (int vertex : traversal) cout << vertex << " ";cout << endl;
}

拓扑排序的 dfs 实现

bool dfs(int node, vector<vector<int>> &adj, vector<int> &visited, stack<int> &result)
{// 当前节点正在访问,图中有环if (visited[node] == 1)return false; // 当前节点已经访问过if (visited[node] == 2)return true; // 1. 对每个未被访问的节点执行 DFS,标记该节点为访问中visited[node] = 1; for (int neighbor : adj[node])// 2. 如果访问到某个已经在 “ 访问中 ” 状态的节点,则说明图中存在环,无法进行拓扑排序if (!dfs(neighbor, adj, visited, result))return false;// 3. DFS 完成后,标记节点为“已访问”,并将节点加入到结果栈(或者队列)中visited[node] = 2; // 标记为已访问result.push(node); // 将节点加入栈return true;
}vector<int> topologicalSortDFS(int n, vector<vector<int>> &edges)
{vector<vector<int>> adj(n);for (const auto &edge : edges)adj[edge[0]].push_back(edge[1]);vector<int> visited(n, 0); // 0: 未访问, 1: 正在访问, 2: 已访问stack<int> result;// 1. 对每个未被访问的节点执行 DFS,标记该节点为访问中for (int i = 0; i < n; ++i)if (visited[i] == 0)if (!dfs(i, adj, visited, result))return {}; // 如果存在环,返回空vector<int> order;while (!result.empty()){order.push_back(result.top());result.pop();}return order;
}

想到如果同样对 dfs 遍历的返回值改为 bool 值也可以写成

bool MyGraph::dfsVisit(int vertex, vector<bool> &visited, vector<int> &traversal)
{if (visited[vertex])return true;visited[vertex] = true;      traversal.push_back(vertex); for (const auto &edge : adjList[vertex])if (!dfsVisit(edge.first, visited, traversal))return false;return true;
}void MyGraph::DFS(int startVertex)
{vector<bool> visited(n, false); vector<int> traversal;          if (dfsVisit(startVertex, visited, traversal)){cout << "DFS Traversal: ";for (int vertex : traversal){cout << vertex << " ";}cout << endl;}
}

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

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

相关文章

SurfaceFlinger layers合成

HWC&#xff08;Device&#xff09;合成的源码分析 GPU合成源码分析&#xff1a;显示框架之SurfaceFlinger GPU合成 - 简书 不支持device合成的layer&#xff0c;SurfaceFlinger会采用GPU来合成&#xff0c;然后与device合成的layer在hwc进行同步再送给屏幕 8295芯片合成规则…

计算机网络-传输层 TCP协议(上)

目录 报头结构 TCP的可靠传输机制 核心机制一&#xff1a;确认应答 TCP的序号和确认序号 核心机制二&#xff1a;丢包重传 核心机制三&#xff1a;连接管理 建立连接-三次握手 断开连接-四次挥手 核心机制四&#xff1a;滑动窗口 数据包已经抵达, ACK被丢了 数据包就…

5.2章节python字符串的格式化三种方式

在Python中&#xff0c;格式化字符串是编程中常见的任务&#xff0c;它用于将变量或表达式的值嵌入到字符串中。以下是三种常见的格式化字符串的方式&#xff1a; 1.百分号&#xff08;%&#xff09;格式化&#xff1a; 这是Python早期版本中常用的字符串格式化方法。通过在字…

反向传播算法的原理与应用

反向传播算法的原理与应用 反向传播算法是神经网络中用于训练的关键技术&#xff0c;它通过计算代价函数关于网络权重的梯度来更新网络参数。本文将介绍反向传播算法的基本原理和应用。 反向传播算法的基本原理 反向传播算法的核心是链式法则&#xff0c;它允许我们从输出层开…

【经验分享】容器云运维的知识点

最近忙于备考没关注&#xff0c;有次点进某小黄鱼发现首页出现了我的笔记还被人收费了 虽然我也卖了一些资源&#xff0c;但我以交流、交换为主&#xff0c;笔记都是免费给别人看的 由于当时刚刚接触写的并不成熟&#xff0c;为了避免更多人花没必要的钱&#xff0c;所以决定公…

蓝卓生态说 | 东实总经理张岑:以行业、产品、服务为关键词,持续提升用户体验

成功的产品离不开开放式创新和生态协同的力量。近年来&#xff0c;蓝卓坚持“平台生态”战略&#xff0c;不断加码生态&#xff0c;提出三个层次的开源开放生态计划&#xff0c;举办“春风行动”、“生态沙龙”等系列活动&#xff0c;与生态伙伴共生、共创、共同推动工业互联网…

Spring Boot 集成 MyBatis 全面讲解

Spring Boot 集成 MyBatis 全面讲解 MyBatis 是一款优秀的持久层框架&#xff0c;与 Spring Boot 集成后可以大大简化开发流程。本文将全面讲解如何在 Spring Boot 中集成 MyBatis&#xff0c;包括环境配置、基础操作、高级功能和最佳实践。 一、MyBatis 简介 1. SqlSession …

OpenGL ES详解——glUniform1i方法是否能用于设置纹理单元

glUniform1i 方法确实可以用于设置纹理单元&#xff08;texture unit&#xff09;。在OpenGL中&#xff0c;纹理单元是图形硬件的一部分&#xff0c;它允许你同时绑定多个纹理&#xff0c;并在着色器程序中通过uniform变量来选择使用哪个纹理。 通常&#xff0c;纹理单元通过整…

Keil-MDK开发环境编译后axf自动转换bin格式文件

编译选项添加如下&#xff0c;调用fromelf工具自动完成转换&#xff1a; fromelf --bin -o "$LL.bin" "#L"

大模型qiming面试内容整理-编码能力评估

编码能力评估是大模型相关岗位面试中非常关键的一环,面试官通常希望通过这个环节了解候选人对编程语言、算法与数据结构的掌握情况,以及其在实践中解决实际问题的能力。以下是编码能力评估的常见内容和类型,特别是针对机器学习、大模型和深度学习方向: 编程语言熟练度 ● P…

LeetCode hot100-74

https://leetcode.cn/problems/kth-largest-element-in-an-array/description/?envTypestudy-plan-v2&envIdtop-100-liked 215. 数组中的第K个最大元素 已解答 中等 相关标签 相关企业 给定整数数组 nums 和整数 k&#xff0c;请返回数组中第 k 个最大的元素。请注意&…

Python爬虫之Selenium的应用

【1】Selenium基础介绍 1.什么是selenium&#xff1f; &#xff08;1&#xff09;Selenium是一个用于Web应用程序测试的工具。 &#xff08;2&#xff09;Selenium 测试直接运行在浏览器中&#xff0c;就像真正的用户在操作一样。 &#xff08;3&#xff09;支持通过各种driv…

MySQL 存储过程与函数:增强数据库功能

一、MySQL 存储过程与函数概述 &#xff08;一&#xff09;存储过程的定义与特点 存储过程是一组预编译的 SQL 语句集合&#xff0c;它们被存储在数据库中&#xff0c;可根据需要被重复调用。例如&#xff0c;在一个电商系统中&#xff0c;经常需要查询某个时间段内的订单数据…

【超详细实战攻略】Jmeter逻辑控制器中if控制器、模块控制器、测试片段的使用方法

【超详细实战攻略】Jmeter逻辑控制器中if控制器、模块控制器、测试片段的使用方法 1 搭建测试对象1.1 禅道下载1.2 禅道安装1.3 运行禅道1.4 接口查看1.5 接口选择 2 Jmeter前置操作2.1 创建Jmeter线程组2.2 创建信息头管理器和请求默认值2.3 添加获取token接口2.4 添加监听器 …

【前端面试题】变量提升、闭包、promise

飞书面试 题目1&#xff1a; async function foo() {console.log(foo start);await bar();console.log(foo end); }async function bar() {console.log(bar start);return new Promise((resolve, reject) > {setTimeout(() > {console.log(bar promise);resolve();}, 1…

【Mysql】索引下推、索引合并详解

文章目录 1. 索引下推&#xff08;Index Condition Pushdown, ICP&#xff09;定义工作机制实现过程优化的典型场景 2. 索引合并&#xff08;Index Merge&#xff09;定义索引合并方式使用限制 3. 对比与应用场景选用建议 这篇文章就简单的给大家介绍下索引下推、索引合并 1. 索…

智能时代的基石:神经网络

智能时代的基石&#xff1a;神经网络 第一节&#xff1a;神经网络简介 课程目标 本节课程旨在全面介绍神经网络的基本概念、结构以及其在历史发展中的重要里程碑。通过深入理解神经网络的工作原理和演变过程&#xff0c;学员将能够掌握神经网络在现实世界中的多种应用&#…

8_Sass 颜色函数 --[CSS预处理]

Sass 提供了一系列的颜色函数&#xff0c;允许开发者在 CSS 中动态地创建和操作颜色。这些函数可以用于生成调色板、调整颜色的亮度或饱和度、混合颜色等&#xff0c;从而提高样式表的灵活性和可维护性。以下是 Sass 中一些常用的颜色函数及其用法示例&#xff1a; 1. adjust-…

java和go语言的优劣

Java 和 Go 是两种非常流行的编程语言&#xff0c;各自拥有独特的特性和优势。它们在不同的应用场景中表现出色&#xff0c;选择哪种语言取决于具体的项目需求、团队技能以及个人偏好。下面我们将从多个维度对比 Java 和 Go 的优劣&#xff0c;帮助您更好地理解这两种语言的特点…

【力扣算法】234.回文链表

快慢指针&#xff1a;一个指针走两步&#xff0c;一个指针走一步&#xff0c;当快指针走到链表末尾时&#xff0c;慢指针走到中间位置。 逆转链表&#xff1a;根据指针位置分成两个表&#xff0c;逆转第二个表。 按序判断就可以&#xff0c;如果是相同就是回文&#xff0c;反之…