图论与算法(3)图的深度优先遍历

news2024/11/28 16:36:35

1. 遍历的意义

1.1 图的遍历

图的遍历是指按照一定规则访问图中的所有顶点,以便获取图的信息或执行特定操作。常见的图遍历算法包括深度优先搜索(DFS)和广度优先搜索(BFS)。

深度优先搜索(DFS):从起始顶点开始,递归或使用栈的方式访问相邻的顶点,直到所有顶点都被访问过为止。DFS通过探索图的深度来遍历图,一直沿着路径向下直到无法继续,然后回溯到前一个顶点,继续探索其他路径。

广度优先搜索(BFS):从起始顶点开始,逐层访问其相邻顶点,先访问距离起始顶点最近的顶点,然后依次访问距离起始顶点更远的顶点。BFS通过探索图的广度来遍历图,先访问离起始顶点最近的顶点,然后依次访问其他相邻的顶点。

这两种遍历算法可以用于有向图和无向图,并且可以用来解决很多与图相关的问题,例如寻找路径、判断连通性、查找最短路径等。

1.2 树的遍历

树的遍历算法题链接:树结构及遍历

示例-前序遍历:

class TreeNode { 
    int val;
    TreeNode left;
    TreeNode right;
    
    public TreeNode(int val) {
        this.val = val;
    }
}

public class TreeTraversal {

    public void preorderTraversal(TreeNode root) {
        if (root == null) {
            return;
        }

        System.out.print(root.val + " "); // 访问根节点
        preorderTraversal(root.left);     // 前序遍历左子树
        preorderTraversal(root.right);    // 前序遍历右子树
    }
}

2. 图的深度优先遍历-前序遍历

public class GraphDFS {

    private Graph G;           // 顶点数
    private boolean [] visited;         // 边数
    private ArrayList<Integer> order = new ArrayList();

    public GraphDFS(Graph G){
        this.G = G;
        visited = new boolean[G.V()];
        dfs(0);
    }

    private void dfs(int v){
        visited[v] = true;
        order.add(v);

        for (int w : G.adj(v)) {
            if (!visited[w]) {
                dfs(w);
            }
        }
    }

    public Iterable<Integer> order(){
        return order;
    }
}

该递归方法按照以下步骤进行遍历:

  1. 选择一个起始节点 v 进行遍历,并将其标记为已访问。
  2. 输出当前节点的值。
  3. 对于当前节点 v 的每个邻接节点 w,如果邻接节点 w 尚未访问,则递归调用该方法,以节点 w 作为新的起始节点,继续遍历。
  4. 重复步骤2和步骤3,直到所有节点都被访问过。

该递归方法的关键在于递归调用。通过递归,当遍历到一个节点的邻接节点时,会先访问邻接节点,然后再递归访问邻接节点的邻接节点,以此类推,直到遍历完所有可达的节点。这样就实现了深度优先搜索的效果。

在遍历过程中,使用一个布尔类型的数组 visited 来标记节点是否已访问。初始时,所有节点的访问状态都设置为 false。在遍历过程中,将访问过的节点标记为 true,以避免重复访问。

通过递归调用和节点的访问状态标记,该方法能够深入到图的每个连通分量,并逐个访问每个节点,确保不会漏掉任何节点。

代码运行结果:

    public static void main(String[] args) {
        Graph graph = new Graph("g.txt");
        GraphDFS graphDFS = new GraphDFS(graph);
        System.out.println(graphDFS.order());
    }

   [0, 1, 2, 3, 4, 5, 6]

   Process finished with exit code 0

上述优先遍历逻辑的问题

该方法在遍历过程中只能遍历到与起始节点连通的顶点,对于不连通的顶点是无法遍历到的。

在构造函数 GraphDFS(Graph G) 中,使用深度优先搜索算法进行遍历的起始节点是固定的,即始终从顶点0开始。然后在 dfs(int v) 方法中,通过递归调用遍历与当前节点相邻的节点。由于该算法的起始节点是固定的,因此只能访问到与起始节点连通的顶点。

如果图中存在多个连通分量(即图中有多个独立的子图),且起始节点只属于其中一个连通分量,那么其他连通分量中的顶点是无法通过该方法遍历到的。

要遍历整个图,需要对每个顶点都调用深度优先搜索算法进行遍历,以确保遍历到所有的顶点。可以通过循环遍历图中的每个顶点,并对未访问过的顶点调用深度优先搜索方法来实现。

改进构造器方法:

    public GraphDFS(Graph G){
        this.G = G;
        visited = new boolean[G.V()];
        for (int v = 0; v < G.V(); v++ ){
            if (!visited[v]){
                dfs(v);
            }
        }
    }

3. 图的深度优先遍历-后序遍历

public class GraphDFS {

    private Graph G;           // 顶点数
    private boolean [] visited;         // 边数
    private ArrayList<Integer> pre = new ArrayList();  // 先序遍历
    private ArrayList<Integer> post = new ArrayList();   // 后序遍历

    public GraphDFS(Graph G){
        this.G = G;
        visited = new boolean[G.V()];
        for (int v = 0; v < G.V(); v++ ){
            if (!visited[v]){
                dfs(v);
            }
        }
    }

    private void dfs(int v){
        visited[v] = true;
        pre.add(v);

        for (int w : G.adj(v)) {
            if (!visited[w]) {
                dfs(w);
            }
        }
        post.add(v);
    }

    public Iterable<Integer> pre(){
        return pre;
    }

    public Iterable<Integer> post(){
        return post;
    }

    public static void main(String[] args) {
        Graph graph = new Graph("g.txt");
        GraphDFS graphDFS = new GraphDFS(graph);
        System.out.println(graphDFS.pre());
        System.out.println(graphDFS.post());
    }
}

上述代码实现了图的后序遍历。主要的实现思路如下:

GraphDFS类中,定义了一个私有成员变量prepost,它们分别用于存储前序遍历和后序遍历的顶点顺序。

GraphDFS的构造函数中,遍历图中的所有顶点。对于每个未被访问过的顶点,调用dfs方法进行深度优先搜索。

dfs方法中,首先将当前顶点标记为已访问,并将其添加到pre列表中,表示前序遍历的顺序。

然后遍历当前顶点的邻接顶点,如果邻接顶点未被访问过,则递归调用dfs方法进行深度优先搜索。在递归回溯时,将当前顶点添加到post列表中,表示后序遍历的顺序。

最后,通过调用pre()post()方法,可以获取到前序遍历和后序遍历的顶点顺序。

4. 复杂度分析

优先搜索的过程中,每个顶点只会被访问一次。

对于稀疏图(边数接近顶点数的数量级)而言,深度优先遍历的时间复杂度可以近似地表示为O(V+E),其中V是顶点数,E是边数。这是因为在每个顶点上进行一次访问的操作,以及遍历每条边的操作都需要一定的时间。

对于稠密图(边数接近V^2的数量级)而言,深度优先遍历的时间复杂度可以近似地表示为O(V^2),其中V是顶点数。这是因为在每个顶点上进行一次访问的操作,以及遍历每个顶点的邻接列表的操作都需要一定的时间。

上述示例中,是稀疏图,所以,其时间复杂度为 O(V+E)。

总结而言,深度优先遍历的时间复杂度与图的规模有关,一般情况下可以近似表示为O(V+E)或O(V^2)。

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

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

相关文章

UART串口通信实验

不管是单片机开发还是嵌入式 Linux 开发&#xff0c;串口都是最常用到的外设。 可以通过串口将开发板与电脑相连&#xff0c;然后在电脑上通过串口调试助手来调试程序。 还有很多模块&#xff0c;比如蓝牙、GPS、GPRS等都使用串口与主控进行通信。 UART简介 串口全称串行接口…

vb6 Webview2微软Edge Chromium内核执行JS取网页数据测速

微软Edge Chromium内核执行JS获取网页数据测试 ExcuteScript eval(document.body.innerHTML) from : https://www.163.com 采集的网页HTM字符串占用字节空间1.2MB ExcuteScript回调事件中取得JS执行结果&#xff0c;用时 54 毫秒 其中JSON转字符13.5209毫秒 jSON数据长度: 增…

ChatGPT更新说明(20230524)

原文传送门&#xff1a;ChatGPT — Release Notes 更新说明&#xff08;5月24日&#xff09; 简要&#xff1a;iOS应用在更多国家可用&#xff0c;Alpha测试中的共享链接&#xff0c;Bing插件&#xff0c;iOS上的历史记录禁用 ChatGPT iOS应用在更多国家可用 好消息&#xf…

Elasticsearch:如何使用集群级别的分片分配过滤(不包括节点)安全地停用节点

当你想停用 Elasticsearch 中的节点时&#xff0c;通常的过程不是直接销毁节点。 如果你这样做&#xff0c;那么你就有数据丢失的风险&#xff0c;这不是你想要对应该是可靠的数据库做的事情。 这样做的问题是&#xff0c;节点很可能会通过 Elasticsearch 处理的恰当命名的分片…

Character.AI成为新晋AI聊天应用爆款;谷歌推出 Google Slides AI 图像生成

&#x1f989; AI新闻 &#x1f680; Character.AI&#xff1a;首周下载量超越ChatGPT&#xff0c;成为新晋AI聊天应用爆款 摘要&#xff1a;Character.AI是一款受欢迎的人工智能聊天应用&#xff0c;用户可以自由创建AI角色&#xff0c;并与它们聊天。该应用于2023年5月23日…

C#,码海拾贝(32)——计算“实对称三对角阵的全部特征值与特征向量的”之C#源代码,《C#数值计算算法编程》源代码升级改进版

using System; namespace Zhou.CSharp.Algorithm { /// <summary> /// 矩阵类 /// 作者&#xff1a;周长发 /// 改进&#xff1a;深度混淆 /// https://blog.csdn.net/beijinghorn /// </summary> public partial class Matrix {…

【Mysql】 表的约束

文章目录 【Mysql】 表的约束空属性默认值列描述zerofill主键自增长唯一键外键综合案例 【Mysql】 表的约束 上一个博客记录的是mysql中的类型&#xff0c;这篇博客记录的是mysql中的表的约束&#xff1b;即列字段对插入数据的约束 空属性 俩个值&#xff1a; null (默认) 和…

Vue3 + ElementPlus实战学习——模拟简单的联系人列表管理后台

文章目录 &#x1f4cb;前言&#x1f3af;demo 介绍&#x1f3af;功能分析&#x1f9e9;数据的展示与分页功能&#x1f9e9;编辑功能&#x1f9e9;删除功能 &#x1f3af;部分代码分析&#x1f3af;完整代码&#x1f4dd;最后 &#x1f4cb;前言 这篇文章介绍一下基于 Vue3 和…

DataSpell第一次安装使用教程

官网&#xff1a; Download DataSpell: The IDE for Data Scientists (jetbrains.com) 双击.exe文件开始安装 安装过程就一直点击下一步就好&#xff0c;遇到方框需要勾选的全部勾上。 注意尽量别安装在C盘&#xff0c;我安装在了D盘。 获取jihuoma&#xff1a;(484条消息)…

MySql学习1:安装

前言 学习教程&#xff1a;黑马程序员 MySQL数据库入门到精通&#xff0c;从mysql安装到mysql高级、mysql优化全囊括 目前的打算是跟着教程学习基础部分&#xff0c;进阶和运维部分以后可能会学习。 安装 关于如何安装mysql可以跟着视频里的操作&#xff0c;但是对于我这种…

盘点一个AI你画我猜的小工具

点击上方“Python爬虫与数据挖掘”&#xff0c;进行关注 回复“书籍”即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 寻声暗问弹者谁&#xff0c;琵琶声停欲语迟。 大家好&#xff0c;我是Python进阶者。 一、前言 前几天在【ChatGPT&AI破局俱乐部】知识星球发现了一…

【Python】Python系列教程-- Python3 字典(十四)

文章目录 前言创建空字典访问字典里的值修改字典删除字典元素字典键的特性字典内置函数&方法 前言 往期回顾&#xff1a; Python系列教程–Python3介绍&#xff08;一&#xff09;Python系列教程–Python3 环境搭建&#xff08;二&#xff09;Python系列教程–Python3 VS…

【Java】Java(四十七):单元测试

文章目录 1. 概述2. 特点3. 使用步骤4. 相关注解5. 疑惑: 有了main函数 为啥还要 单元测试6. 后记 1. 概述 JUnit是一个 Java 编程语言的单元测试工具。JUnit 是一个非常重要的测试工具 2. 特点 JUnit是一个开放源代码的测试工具。提供注解来识别测试方法。JUnit测试可以让…

在k8s平台部署个人博客(三)

先下载实战-在k8s平台部署个人博客-资源包 再K8s部署个人博客 实验步骤如下&#xff1a; [rootk8s-master]# kubectl create secret generic mysql-pass --from-literalpasswordYOUR_PASSWORD #把mysql.tar.gz和wordpress.tar.gz上传到K8s工作节点&#xff0c;手动解压即可…

java企业级信息系统开发学习笔记09 利用MyBatis实现CRUD操作

文章目录 一、学习目标利用MyBatis查询表记录利用MyBatis插入表记录利用MyBatis更新表记录利用MyBatis删除表记录 二、查询表记录1.打开mybatis项目&#xff08;一&#xff09;在映射器配置文件里引入结果映射元素&#xff08;二&#xff09;添加按姓名查询用户记录功能1、添加…

软考——下午题部分,例题一,二,三,六

例题一 11年上半年 病人&#xff0c;护理人员&#xff0c;医生 D 生命体征范围文件 日志文件 病历文件 治疗意见文件 14年上 E1 巴士司机,2 机械师,3 会计,4 主管,5 库存管理系统 D 巴士列表文件 维修记录文件 部件清单 人事档案 14年下 1 客户 2 供应商 D 销售订单表 库存…

基于simulink仿真弹跳球

一、前言 示例可视化了一个从地板上弹起的球。球在撞击地板时变形&#xff0c;保持球的体积恒定。变形是通过修改球的刻度场来实现的。 弹跳球实验有以下几个意义&#xff1a; 1. 研究物体的弹性&#xff1a;弹跳球实验可以帮助我们了解不同物体的弹性特性&#xff0c;包括弹性…

高校全奖PhD招生、大厂全职/实习招聘合集来了!快来拿offer!

本周&#xff0c;招聘小助手从「AI 求职」公众号中整理了来自 6 所高校和 6 家用人单位的「人工智能」相关全奖博士招生、算法实习等招聘信息。 分别来自新加坡国立大学、香港科技大学&#xff08;广州&#xff09;、华盛顿大学、字节跳动、小红书、京东、IDEA研究院等国内外知…

如何通过控制点或地物点生产地方坐标系的倾斜摄影三维模型数据?

如何通过控制点或地物点生产地方坐标系的倾斜摄影三维模型数据&#xff1f; 要生成地方坐标系的倾斜摄影三维模型数据&#xff0c;需要进行以下步骤&#xff1a; 1、收集影像数据 首先需要采集大量的航空影像和地面影像&#xff0c;以构建真实世界中的物体模型。这些影像可以…

Electron+Vue+Vite: 开发实践—初始化项目

运行系统:Apple M1 ,16 GB 开发工具:VSCode NodeJS:18.10 参考:https://github.com/electron-vite/electron-vite-vue.git 文章目录 创建项目构建项目客户端构建网页构建创建项目 npm create electron-vitecd electron-vite-tempsudo yarn installsudo yarn d