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

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

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

在这里插入图片描述

电路图

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

在这里插入图片描述

图的定义及分类

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

在这里插入图片描述

特殊的图

  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 queuefor (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顶点的临接表,得到每一个顶点wfor (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.hqwc.cn/news/1225.html

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

相关文章

2023年华中杯数学建模B题小学数学应用题相似性度量及难度评估解题全过程文档及程序

2023年华中杯数学建模 B题 小学数学应用题相似性度量及难度评估 原题再现 某 MOOC 在线教育平台希望能够进行个性化教学&#xff0c;实现用户自主学习。在用户学习时&#xff0c;系统从题库中随机抽取若干道与例题同步的随堂测试题&#xff0c;记录、分析学生的学习和答题信息…

HTML5新特性总结

新增语义化标签 新增了很多语义化标签&#xff0c;如header、footer、nav、article、section(页面中的某段文字&#xff0c;或文章中的某段文字)、aside、main 其中article标签里可以包含多个section&#xff1b; section强调的是分段或分块&#xff0c;若想将一块内容分成几…

【TCP/IP】IP地址与域名之间的转换 - gethostbyname 和 gethostbyaddr函数

目录 域名系统 DNS服务器 IP地址和域名之间的转换 通过域名获取IP地址 通过IP地址获取域名 域名系统 域名系统&#xff08;英文&#xff1a;Domain Name System&#xff0c;缩写&#xff1a;DNS&#xff09;是互联网的一项服务。它作为将域名和IP地址相互映射的一个分布式…

物联网助力鲜花冷链安全——温湿度监控系统

近几年来我国花卉生产的发展尤为迅速&#xff0c;生产面积逐年扩大&#xff0c;产值成倍增长&#xff0c;内销市场越来越旺&#xff0c;出口创汇也有较大幅度上升。 随着人民生活水平的提高和可支配收入的增加&#xff0c;人们对鲜花的需求日益增长&#xff0c;花卉市场的前景…

图书搜索领域重大突破!用Apache SeaTunnel、Milvus和OpenAI提高书名相似度搜索精准度和效率

作者 | 刘广东&#xff0c;Apache SeaTunnel Committer 背景 目前&#xff0c;现有的图书搜索解决方案&#xff08;例如公共图书馆使用的解决方案&#xff09;十分依赖于关键词匹配&#xff0c;而不是对书名实际内容的语义理解。因此会导致搜索结果并不能很好地满足我们的需…

C#项目练习系列--1.倒计时器

C#项目练习系列--1.倒计时器 实操感想代码 实操 总体实现功能&#xff1a;选定计时时间—点击开始计时—进度条和剩余时间显示—提示时间到。 软件版本&#xff1a;VS2019 1.新建工程 选择c#&#xff0c;windows窗体应用&#xff0c;.NET Framework版本选择4或4以下时最后…

【Redis常见命令】 —— 关于Redis的一点儿知识

&#x1f4a7; 【 R e d i s 常见命令】——关于 R e d i s 的一点儿知识 \color{#FF1493}{【Redis常见命令】 —— 关于Redis的一点儿知识} 【Redis常见命令】——关于Redis的一点儿知识&#x1f4a7; &#x1f337; 仰望天空&#xff0c;妳我亦是行人.✨ &#x1f…

【数据挖掘】时间序列教程【一】

第一章 说明 对于时间序列的研究&#xff0c;可以追溯到19世纪末和20世纪初。当时&#xff0c;许多学者开始对时间相关的经济和社会现象进行研究&#xff0c;尝试发现其规律和趋势。其中最早的时间序列研究可以追溯到法国经济学家易贝尔&#xff08;Maurice Allais&#xff09;…

设计模式学习之工厂方法模式

设计模式系列往期文章 设计模式学习之策略模式设计模式学习之策略模式在前端的应用设计模式学习之简单工厂模式 在上一篇文章中我们学习了简单工厂模式——这是工厂模式中最简单的一种模式&#xff0c;通过工厂类提供的方法创建类&#xff08;可以类比为产品&#xff09;&…

界面开发框架Qt新手入门教程:如何使用Calendar组件创建日历(二)

Qt 是目前最先进、最完整的跨平台C开发工具。它不仅完全实现了一次编写&#xff0c;所有平台无差别运行&#xff0c;更提供了几乎所有开发过程中需要用到的工具。如今&#xff0c;Qt已被运用于超过70个行业、数千家企业&#xff0c;支持数百万设备及应用。 本文中的CalendarWi…

主动式和被动式电容笔哪个好用?苹果平板平替笔排行

被动式电容笔与主动式电容笔最大的不同在于主动式电容笔具有更广泛的应用领域&#xff0c;可以与不同种类的电容屏幕进行匹配。随着人们对其了解的不断深入&#xff0c;其应用也日益广泛。除此之外&#xff0c;平替电容笔的技术&#xff0c;也在不断的改进和提高&#xff0c;逐…

ES批量上传数据 - Python操作ES

代码 # -*- coding: utf-8 -*- # Author : markadcimport randomfrom elasticsearch import Elasticsearch, helpersurl http://localhost:9200/ client Elasticsearch(url) index testsome [] for i in range(1, 10001):docu {uid: i, age: random.randint(1, 100)} …