图-深度优先搜索与广度优先搜索

news2024/11/25 2:38:37

在现实生活中,有许多应用场景会包含很多点以及点点之间的连接,而这些应用场景我们都可以用即将要学习的图
这种数据结构去解决

地图
我们生活中经常使用的地图,基本上是由城市以及连接城市的道路组成,如果我们把城市看做是一个一个的点,把
道路看做是一条一条的连接,那么地图就是我们将要学习的图这种数据结构

在这里插入图片描述

电路图

下面是一个我们生活中经常见到的集成电路板,它其实就是由一个一个触点组成,并把触点与触点之间通过线进行
连接,这也是我们即将要学习的图这种数据结构的应用场景

在这里插入图片描述

图的定义及分类

定义:图是由一组顶点和一组能够将两个顶点相连的边组成的

在这里插入图片描述

特殊的图

  1. 自环:即一条连接一个顶点和其自身的边
  2. 平行边:连接同一对顶点的两条边
    在这里插入图片描述

图的分类

按照连接两个顶点的边的不同,可以把图分为以下两种

  • 无向图:边仅仅连接两个顶点,没有其他含义
  • 有向图:边不仅连接两个顶点,并且具有方向

无向图

图的相关术语

相邻顶点

当两个顶点通过一条边相连时,我们称这两个顶点是相邻的,并且称这条边依附于这两个顶点

某个顶点的度就是依附于该顶点的边的个数

子图

是一幅图的所有边的子集(包含这些边依附的顶点)组成的图

路径

是由边顺序连接的一系列的顶点组成

是一条至少含有一条边且终点和起点相同的路径

在这里插入图片描述

连通图

如果图中任意一个顶点都存在一条路径到达另外一个顶点,那么这幅图就称之为连通图

在这里插入图片描述

连通子图

一个非连通图由若干连通的部分组成,每一个连通的部分都可以称为该图的连通子图

图的存储结构

要表示一幅图,只需要表示清楚以下两部分内容即可

  • 图中所有的顶点
  • 所有连接顶点的边

常见的图的存储结构有两种:邻接矩阵和邻接表

邻接矩阵
  • 使用一个V*V的二维数组int [V] [V] adj,把索引的值看做是顶点;
  • 如果顶点v和顶点w相连,我们只需要将adj[v] [w]和adj[w] [v]的值设置为1,否则设置为0即可

在这里插入图片描述

很明显,邻接矩阵这种存储方式的空间复杂度是V^2的,如果我们处理的问题规模比较大的话,内存空间极有可能不够用

邻接表
  • 使用一个大小为V的数组 Queue[V] adj,把索引看做是顶点;
  • 每个索引处adj[v]存储了一个队列,该队列中存储的是所有与该顶点相邻的其他顶点
    在这里插入图片描述

很明显,邻接表的空间并不是是线性级别的,所以后面我们一直采用邻接表这种存储形式来表示图

图的实现

图的API设计
类名Graph
构造方法Graph(int V):创建一个包含V个顶点但不包含边的图
成员方法1.public int V():获取图中顶点的数量
2.public int E():获取图中边的数量
3.public void addEdge(int v,int w):向图中添加一条边 v-w
4.public Queue adj(int v):获取和顶点v相邻的所有顶点
成员变量1.private final int V: 记录顶点数量
2.private int E: 记录边数量
3.private Queue[] adj: 邻接表
代码实现
package com.vmware;

import java.util.ArrayDeque;
import java.util.Queue;

/**
 * @apiNote 基于临接表的图实现
 */
public class Graph {
    //顶点数目
    private int V;
    //边的数目
    private int E;
    //临接表
    private Queue<Integer>[] adj;

    public Graph(int V) {
        this.V = V;
        this.E = 0;
        this.adj = new ArrayDeque[V];
        //init queue
        for (int i = 0; i < this.adj.length; i++) {
            this.adj[i] = new ArrayDeque<>();
        }
    }

    //获取顶点的数目
    public int V() {
        return V;
    }

    //获取边的数目
    public int E() {
        return E;
    }

    //向图中添加一条边
    public void addEdge(int v, int w) {
        adj[v].add(w);
        adj[w].add(v);
        E++;
    }

    //获取和顶点v相邻的所有顶点
    public Queue<Integer> adj(int v) {
        return adj[v];
    }
}

图的搜索

在很多情况下,我们需要遍历图,得到图的一些性质,例如,找出图中与指定的顶点相连的所有顶点,或者判定某个顶点与指定顶点是否相通,是非常常见的需求

有关图的搜索,最经典的算法有深度优先搜索和广度优先搜索,接下来我们分别讲解这两种搜索算法

深度优先搜索

所谓的深度优先搜索,指的是在搜索时,如果遇到一个结点既有子结点,又有兄弟结点,那么先找子结点,然后找
兄弟结点

在这里插入图片描述

很明显,在由于边是没有方向的,所以,如果4和5顶点相连,那么4会出现在5的相邻链表中,5也会出现在4的相邻链表中,那么为了不对顶点进行重复搜索,应该要有相应的标记来表示当前顶点有没有搜索过,可以使用一个布尔类型的数组 boolean[V] marked,索引代表顶点,值代表当前顶点是否已经搜索,如果已经搜索,标记为true,如果没有搜索,标记为false

API设计

类名DepthFirstSearch
构造方法DepthFirstSearch(Graph G,int s):构造深度优先搜索对象,使用深度优先搜索找出G图中s顶点的所有相通顶点
成员方法1.private void dfs(Graph G, int v):使用深度优先搜索找出G图中v顶点的所有相通顶点
2.public boolean marked(int w):判断w顶点与s顶点是否相通
3.public int count():获取与顶点s相通的所有顶点的总数
成员变量1.private boolean[] marked: 索引代表顶点,值表示当前顶点是否已经被搜索
2.private int count:记录有多少个顶点与s顶点相通

代码实现

package com.vmware;

/**
 * @apiNote 深度优先搜索实现
 */
public class DepthFirstSearch {
    //索引代表顶点,value表示当前顶点是否已经被搜索
    private boolean[] marked;
    //记录有多少顶点与s顶点相通
    private int count;

    //构建深度优先搜索对象,使用深度优先搜索找出图中s顶点的所有相通节点
    public DepthFirstSearch(Graph graph, int s) {
        marked = new boolean[graph.V()];//创建一个和图的顶点数一样大小的布尔数组
        dfs(graph, s);                  //搜索G图中与顶点s相通的所有顶点
    }

    //使用深度优先搜索找出G图中v顶点的所有想通节点
    private void dfs(Graph graph, int v) {
        //将当前顶点标记为已搜索
        marked[v] = true;
        //遍历v顶点的临接表,得到每一个顶点w
        for (Integer w : graph.adj(v)) {
            //如果顶点没有被搜索过,则递归搜索与顶点相通的其他顶点
            if (!marked[w]) {
                count++;
                dfs(graph, w);
            }
        }
    }

    //判断w顶点与s顶点是否相通
    public boolean marked(int w) {
        return marked[w];
    }

    //获取与顶点s相通的所有顶点的总数
    public int count() {
        return count;
    }
}
广度优先搜索

所谓的深度优先搜索,指的是在搜索时,如果遇到一个结点既有子结点,又有兄弟结点,那么先找兄弟结点,然后找子结点

在这里插入图片描述

API设计

类名BreadthFirstSearch
构造方法BreadthFirstSearch(Graph G,int s):构造广度优先搜索对象,使用广度优先搜索找出G图中s顶点的所有相邻顶点
成员方法1.private void bfs(Graph G, int v):使用广度优先搜索找出G图中v顶点的所有相邻顶点
2.public boolean marked(int w):判断w顶点与s顶点是否相通
3.public int count():获取与顶点s相通的所有顶点的总数
成员变量1.private boolean[] marked: 索引代表顶点,值表示当前顶点是否已经被搜索
2.private int count:记录有多少个顶点与s顶点相通
3.private Queue waitSearch: 用来存储待搜索邻接表的点

代码实现

package com.vmware;

import java.util.ArrayDeque;
import java.util.Queue;

/**
 * @apiNote 图的深度优先搜索实现
 */
public class BreadthFirstSearch {
    private boolean[] marked;//索引代表顶点,值表示当前顶点是否被搜索

    private int count; //记录有多少个顶点与s顶点相通

    private Queue<Integer> waitSearch;//用来存储待搜索临接表的点

    //构造广度优先搜索对象,使用广度优先搜索找出G图中s顶点的所有相邻顶点
    public BreadthFirstSearch(Graph graph, int s) {
        //创建一个和图的顶点数一样大小的布尔数组
        marked = new boolean[graph.V()];
        //初始化待搜索的顶点的队列
        waitSearch = new ArrayDeque<>();
        //搜索图中与顶点s相通的所有顶点
        bfs(graph, s);
    }

    //使用广度优先搜索找出图中v顶点的所有相邻顶点
    private void bfs(Graph graph, int v) {
        //标记顶点v为已搜索
        marked[v] = true;
        //添加待搜索顶点到队列中,等待搜索ta的邻接表
        waitSearch.add(v);
        while (!waitSearch.isEmpty()) {
            //从队列中弹出待搜索元素
            Integer s = waitSearch.poll();
            //获取顶点的临节点队列进行遍历
            for (Integer w : graph.adj(s)) {
                //如果临节点是没有被访问过的,则对其进行访问添加到队列,并标记
                if (!marked[w]) {
                    marked[w] = true;
                    waitSearch.add(w);
                    count++;
                }
            }
        }
    }

    //判断w顶点与s顶点是否想相通
    public boolean marked(int w) {
        return marked[w];
    }

    //获取与顶点s相通的所有顶点总数
    public int count() {
        return count;
    }
}

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

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

相关文章

西安石油大学 C++期末考试 重点知识点+题目复习(上)

第一章 “const”关键字的用法 当使用 const 修饰变量、函数参数、成员函数以及指针时&#xff0c;以下是一些代码示例&#xff1a; 声明只读变量&#xff1a; const int MAX_VALUE 100; const float PI 3.14;保护函数参数&#xff1a; void printArray(const int arr[]…

解决vmware虚拟机,克隆修改ip后,xshell连接不上问题

1、查看网卡 ifconfig2、修改网卡配置 vim /etc/sysconfig/network-scripts/ifcfg-ens32 改成与上图一样 修改后 3、重启reboot则解决

STM32F407 串口配置步骤

介绍STM32F407串口配置步骤&#xff0c;完成串口的数据发送与接收、实现中断接收&#xff0c;支持printf重定向。 STM32F407 串口配置说明 STM32F4 的串口资源相当丰富的&#xff0c;功能也相当强劲&#xff0c;STM32F407ZGT6 最多可提供 6 路串口&#xff0c;有分数波特率发…

【Junit 单元测试】

Junit 单元测试 笔记记录 1. Junit介绍2. 使用Junit3. 常用注解4. 断言使用 1. Junit介绍 2. 使用Junit 1.导入依赖 <dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>tes…

C语言-基础语法学习-4 字符串

目录 字符串C语言字符串及相关函数定义字符数组和字符串的区别sizeof()和strlen()的区别动态开辟字符串野指针常用字符串函数 字符串 C语言字符串及相关函数 在C语言中&#xff0c;字符串是由字符数组表示的一系列字符序列。C语言提供了一些函数来处理字符串&#xff0c;使我…

centos磁盘扩容

解释 PE - 物理块&#xff08;Physical Extent&#xff09; 硬盘上有很多实际物理存在的存储块PV - 物理卷 &#xff08;Physical Volume&#xff09; 物理卷处于最底层&#xff0c;它可以是实际物理硬盘上的分区&#xff0c;也可以是整个物理硬盘(相当于单独做一个分区)&…

CommonJS 和 ES6 module

本文主要自己觉得要记录的点记录下来,不耽误大家时间&#xff0c;会持续更新。 Module对象 Module {id: xxx/demo/1.js, //加载文件的绝对路径path: xxx/demo,// 加载文件所在目录的绝对路径exports: [Function (anonymous)],filename: xxx/demo/1.js,加载文件的绝对路径load…

B/S和C/S详解(嵌入式学习)

B/S和C/S详解 1. C/S1.1 概念1.2 C/S架构的特点 2. B/S2.1 概念2.2 B/S架构的特点2.3 相对于传统的C/S架构的优势 3. B/S架构详解4. B/S架构怎么用&#xff08;CGI、Lighttpd&#xff09; 1. C/S 1.1 概念 C/S&#xff08;Client/Server&#xff09;是一种计算机网络架构模式…

【C++】 Qt-页面布局

文章目录 布局组件和布局按钮练习-用户信息页面布局准备工作设置性别设置年龄设置生日设置邮箱后缀 设置头像创建文件写入文件清空表单信息Buddy&#xff08;伙伴&#xff09;关系Tab顺序 布局组件和布局按钮 Qt的UI设计器中提供了丰富的布局管理功能&#xff0c;组件面板里有…

高效简单解决滑动验证码

前言 做爬虫总会遇到各种各样的反爬限制&#xff0c;其中移动验证码是很重要且常见的一环&#xff0c;今天总结下如何高效破解他的方法&#xff0c;例如下图&#xff1a; 解决思路与方法 首先先来分析下&#xff0c;核心问题其实是要怎么样找到目标缺口的位置&#xff0c;一…

Windows服务启动exe无界面终极解决方案

1、前言 我这个方案&#xff08;C#操作&#xff09;是彻底解决【从Windows服务启动程序exe&#xff0c;程序无界面】问题的终极解决方案&#xff0c;终极方案&#xff0c;绝对的终极方案&#xff0c;本来打算收钱的&#xff0c;还是算了&#xff0c;你们也不容易&#xff0c;关…

网络安全(自学笔记)

如果你真的想通过自学的方式入门web安全的话&#xff0c;那建议你看看下面这个学习路线图&#xff0c;具体到每个知识点学多久&#xff0c;怎么学&#xff0c;自学时间共计半年左右&#xff0c;亲测有效&#xff08;文末有惊喜&#xff09;&#xff1a; 1、Web安全相关概念&am…

Redis 性能管理/优化 缓存雪崩/击穿/穿透

---------------------- Redis 性能管理 ---------------------------------------- ----- 查看Redis内存使用 ----- info memoryredis-cli -a abc123 info memory ----- 内存碎片率 ----- used_memory_rss&#xff1a;是Redis向操作系统申请的内存。used_memory&#xff1a;是…

缺失concrt140.dll下载,找不到concrt140.dll的解决方法

我们平时在打开 Adobe 应用程序、Halo、Forza Horizon 5 等时&#xff0c;可能会遇到找不到 concrt140.dll。因此&#xff0c;这不是特定于某个应用程序的问题。如果没有安装正确的 DLL&#xff0c;应用程序将无法正常工作&#xff0c;因为它们的代码依赖于这些库中编写的代码。…

井盖异动监测传感器:井盖的安全守护者

随着城市化进程的不断加速&#xff0c;城市道路、人行道上的井盖扮演着重要的角色。然而&#xff0c;由于各种因素&#xff0c;如车辆冲击、材料老化等&#xff0c;井盖常常会出现异动情况&#xff0c;井盖异动不仅对行车和行人的安全构成威胁&#xff0c;还给城市基础设施的维…

C#扩展——Visual Studio 代码提示/智能提示字体大小更改方法.

声明&#xff1a;本文为个人笔记&#xff0c;用于学习研究使用非商用&#xff0c;内容为个人研究及综合整理所得&#xff0c;若有违规&#xff0c;请联系&#xff0c;违规必改。 C#扩展——Visual Studio 代码提示/智能提示字体大小更改方法. 文章目录 C#扩展——Visual Studio…

【期末总复习】医学影像学(第2版)周翔平

【选择】 1、垂体腺瘤大小范围这么界定的&#xff1f; P66&#xff0c;肿瘤直径<1cm称为垂体微腺瘤&#xff0c;>1cm称为垂体大腺瘤&#xff0c;>4cm成为巨大腺瘤。 2、当一个车祸伤病人&#xff0c;怀疑长骨骨折首选什么检查方法&#xff1f; P387 X线平片 3、…

leetcode957. N 天后的牢房(java-14天周期优化)

N 天后的牢房 leetcode957. N 天后的牢房题目描述解题思路Java 代码演示 算法专题 leetcode957. N 天后的牢房 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode.cn/problems/prison-cells-after-n-days 题目描述 监狱中 8 间牢房排成一…

力扣 106. 从中序与后序遍历序列构造二叉树

题目来源&#xff1a;https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal/description/ C题解&#xff1a;中序遍历是左中右&#xff0c;后序遍历是左右中&#xff0c;所以拿到两个遍历数组&#xff0c;我们可以从后序遍历获取中间节点…

信号链噪声分析6

目录 概要 整体架构流程 技术名词解释 技术细节 公用时钟源相位噪声的消除 公用电源噪声的消除 小结 概要 提示&#xff1a;这里可以添加技术概要 放大器输出被发送到均衡混频器&#xff08;相位检测器&#xff09;。相位检测器将两 个信号混合&#xff0c;在其输出处产生和积…