数据结构(十)图

文章目录

  • 图的简介
    • 图的定义
    • 图的结构
    • 图的分类
      • 无向图
      • 有向图
      • 带权图(Wighted Graph)
  • 图的存储
    • 邻接矩阵(Adjacency Matrix)
    • 邻接表
      • 代码实现
  • 图的遍历
    • 深度优先搜索(DFS,Depth Fisrt Search)
      • 遍历抖索过程
    • 广度优先搜索(BFS,Breadth First Search)
      • 遍历搜索过程
  • 完整代码

图的简介

图的定义

图(Graph)一种比线性表和树更加复杂的结构。在图形结构中,顶点(vertex)之间的关系是任意的,途中任意两个顶点之间都有可能关联。

图的结构

在这里插入图片描述

  • 顶点(vertex):图中的元素,就叫做顶点。如图:ABCDEF。
  • 边(edge): 顶点之间建立的连接关系,就叫做边。如图:顶点A和顶点B中间的连线。
  • 度(drgree): 跟顶点相连的边的条数,就叫做度。如图:顶点A与B、C、D相连,则A的度就是3。

图的分类

无向图

在这里插入图片描述

如上图,边(edge)没有方向的图叫做无向图

有向图

在这里插入图片描述

如上图,边(edge)有方向的图叫做有向图

带权图(Wighted Graph)

在这里插入图片描述

如上图中,每条边都带有一个权重(weight)的图,就是带权图

图的存储

邻接矩阵(Adjacency Matrix)

邻接矩阵的底层是一个二维数组,如下图,该图可以转化为一个二维数据表格。
在这里插入图片描述

  • 无向图
    如果顶点 i 和顶点 j 之间有边但是没有方向和权重,那么我们就用array[i][j] = array[j][i] = 1,来表示无向图。
    在这里插入图片描述
  • 有向图
    如果顶点 i 到顶点 j 之间,有一条箭头从顶点 i 指向顶点 j 的边,那我们就将 A[i][j]标记为 1。同理,如果有一条箭头从顶点 j 指向顶点 i 的边,我们就将 A[j][i]标记为 1。
    在这里插入图片描述
  • 带权图
    数组中就存储相应值当作权重。
    在这里插入图片描述

邻接表

邻接表中每个顶点对应一条链表,链表中存储的是与这个顶点相连接的其他顶点。
在这里插入图片描述
图中的一个有向图的邻接表的存储方式,前面的数组存储的是所有的顶点,每个顶点后面链接的块代表:前面顶点所指向的顶线和边的权值。如果该点还有其它顶点,则继续在块后面添加即可。

代码实现

定点(Vertex)类:

package com.xxliao.datastructure.graph;/*** @author xxliao* @description: 图 - 定点类* @date 2024/5/29 16:56*/
public class Vertex {// 顶点名称protected String name;// 该顶点出发的边protected Edge edge;public Vertex(String name, Edge edge) {this.name = name;this.edge = edge;}
}

边(Edge)类:

package com.xxliao.datastructure.graph;/*** @author xxliao* @description: 图 - 边类* @date 2024/5/29 16:57*/
public class Edge {// 被指向的顶点protected String name;// 权重protected int weight;// 顶点的下一条边protected Edge next;public Edge(String name, int weight, Edge next) {this.name = name;this.weight = weight;this.next = next;}
}

图(Graph)类:

package com.xxliao.datastructure.graph;import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** @author xxliao* @description: 邻接表实现图* @date 2024/5/29 16:00*/
public class Graph {// 存储顶点容器private Map<String,Vertex> vertexes;public Graph() {this.vertexes = new HashMap<String,Vertex>();}/*** @description  添加顶点* @author  xxliao* @date  2024/5/29 17:02*/public void addVertex(String vertexName) {vertexes.put(vertexName,new Vertex(vertexName,null));}/*** @description  添加边* @author  xxliao* @date  2024/5/29 17:05*/public void addEdge(String beginVertexName,String endVertexName,int weight) {// 获取出发顶点Vertex beginVertex = vertexes.get(beginVertexName);if(beginVertex == null) {// 没有开始顶点,创建beginVertex = new Vertex(beginVertexName,null);vertexes.put(beginVertexName,beginVertex);}// 创建边对象Edge edge = new Edge(endVertexName,weight,null);if(beginVertex.edge == null) {//当前顶点还没有边,直接设置beginVertex.edge = edge;}else {Edge lastEdge = beginVertex.edge;while(lastEdge.next != null) {lastEdge = lastEdge.next;}// 设置到末尾lastEdge.next = edge;}}
}

图的遍历

图的遍历是指,从给定图的任意顶点(可以称为初始顶点)出发,按照某种搜索方法沿着图边访问所有的顶点,且每个顶点仅被访问一次,这个过程就是图的遍历。图的遍历根据搜索过程不用,可以分为深度优先搜索和广度优先搜索。

深度优先搜索(DFS,Depth Fisrt Search)

深度优先搜索,从起点出发,从规定的方向中选择一个方向,不段的往前走,直到无法继续位置,然后尝试另外一个方向,直到最后走完所有顶点。

遍历抖索过程

假设我们有这么一个图,里面有A、B、C、D、E、F、G、H 8 个顶点,点和点之间的联系如下图所示:
在这里插入图片描述必须依赖栈(Stack),特点是后进先出(LIFO)。

  1. 第一步,选择一个起始顶点,例如从顶点 A 开始。把 A 压入栈,标记它为访问过(用红色标记),并输出到结果中。
    在这里插入图片描述

  2. 第二步,寻找与 A 相连并且还没有被访问过的顶点,顶点 A 与 B、D、G 相连,而且它们都还没有被访问过,我们按照字母顺序处理,所以将 B 压入栈,标记它为访问过,并输出到结果中。
    在这里插入图片描述

  3. 第三步,现在我们在顶点 B 上,重复上面的操作,由于 B 与 A、E、F 相连,如果按照字母顺序处理的话,A 应该是要被访问的,但是 A 已经被访问了,所以我们访问顶点 E,将 E 压入栈,标记它为访问过,并输出到结果中。
    在这里插入图片描述

  4. 第四步,从 E 开始,E 与 B、G 相连,但是B刚刚被访问过了,所以下一个被访问的将是G,把G压入栈,标记它为访问过,并输出到结果中。在这里插入图片描述

  5. 第五步,现在我们在顶点 G 的位置,由于与 G 相连的顶点都被访问过了,类似于我们走到了一个死胡同,必须尝试其他的路口了。所以我们这里要做的就是简单地将 G 从栈里弹出,表示我们从 G 这里已经无法继续走下去了,看看能不能从前一个路口找到出路。
    在这里插入图片描述 如果发现周围的顶点都被访问了,就把当前的顶点弹出。

  6. 第六步,现在栈的顶部记录的是顶点 E,我们来看看与 E 相连的顶点中有没有还没被访问到的,发现它们都被访问了,所以把 E 也弹出去。
    在这里插入图片描述

  7. 第七步,当前栈的顶点是 B,看看它周围有没有还没被访问的顶点,有,是顶点 F,于是把 F 压入栈,标记它为访问过,并输出到结果中。
    在这里插入图片描述

  8. 第八步,当前顶点是 F,与 F 相连并且还未被访问到的点是 C 和 D,按照字母顺序来,下一个被访问的点是 C,将 C 压入栈,标记为访问过,输出到结果中。在这里插入图片描述

  9. 第九步,当前顶点为 C,与 C 相连并尚未被访问到的顶点是 H,将 H 压入栈,标记为访问过,输出到结果中。在这里插入图片描述

  10. 第十步,当前顶点是 H,由于和它相连的点都被访问过了,将它弹出栈。在这里插入图片描述

  11. 第十一步,当前顶点是 C,与 C 相连的点都被访问过了,将 C 弹出栈。在这里插入图片描述

  12. 第十二步,当前顶点是 F,与 F 相连的并且尚未访问的点是 D,将 D 压入栈,输出到结果中,并标记为访问过。在这里插入图片描述

  13. 第十三步,当前顶点是 D,与它相连的点都被访问过了,将它弹出栈。以此类推,顶点 F,B,A 的邻居都被访问过了,将它们依次弹出栈就好了。最后,当栈里已经没有顶点需要处理了,我们的整个遍历结束。

广度优先搜索(BFS,Breadth First Search)

遍历搜索过程

假设我们有这么一个图,里面有A、B、C、D、E、F、G、H 8 个顶点,点和点之间的联系如下图所示,
对这个图进行深度优先的遍历。
在这里插入图片描述

依赖队列(Queue),先进先出(FIFO)。
一层一层地把与某个点相连的点放入队列中,处理节点的时候正好按照它们进入队列的顺序进行。

  1. 第一步,选择一个起始顶点,让我们从顶点 A 开始。把 A 压入队列,标记它为访问过(用红色标记)。
    在这里插入图片描述
  2. 第二步,从队列的头取出顶点 A,打印输出到结果中,同时将与它相连的尚未被访问过的点按照字母大
    小顺序压入队列,同时把它们都标记为访问过,防止它们被重复地添加到队列中。
    在这里插入图片描述
  3. 第三步,从队列的头取出顶点 B,打印输出它,同时将与它相连的尚未被访问过的点(也就是 E 和 F)
    压入队列,同时把它们都标记为访问过。
    在这里插入图片描述
  4. 第四步,继续从队列的头取出顶点 D,打印输出它,此时我们发现,与 D 相连的顶点 A 和 F 都被标记
    访问过了,所以就不要把它们压入队列里。
    在这里插入图片描述
  5. 第五步,接下来,队列的头是顶点 G,打印输出它,同样的,G 周围的点都被标记访问过了。我们不做
    任何处理。
    在这里插入图片描述
  6. 第六步,队列的头是 E,打印输出它,它周围的点也都被标记为访问过了,我们不做任何处理。
    在这里插入图片描述
  7. 第七步,接下来轮到顶点 F,打印输出它,将 C 压入队列,并标记 C 为访问过。
    在这里插入图片描述
  8. 第八步,将 C 从队列中移出,打印输出它,与它相连的 H 还没被访问到,将 H 压入队列,将它标记为
    访问过。
    在这里插入图片描述
    9.第九步,队列里只剩下 H 了,将它移出,打印输出它,发现它的邻居都被访问过了,不做任何事情。
    在这里插入图片描述
  9. 第十步,队列为空,表示所有的点都被处理完毕了,程序结束。

完整代码

https://github.com/xxliao100/datastructure_algorithms.git

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

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

相关文章

【搜索方法推荐】高效信息检索方法和实用网站推荐

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

同时执行多个python脚本扫描,报如下错误,原因为文件越大读取到内存占用内存越多。

killed nohup python $file unable to fork process cannot allocate memory ls: error while loading shared libraries: libdl.so.2 failed to map segment from shared object cannot allocate memory python进程被系统或者某个用户通过 kill 命令强制终止了

Springboot 实战运用

一&#xff0c;基本配置 1&#xff0c;pom文件配置介绍 1.1继承 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.2</version><relativePath/> <…

ubuntu下载离线软件包及依赖

目录 一、前言 二、正文 1.准备环境 2.开始下载 3.后续工作 三、总结 一、前言 由于给客户提供的设备机不允许上网&#xff0c;那么所有待安装的软件包及依赖库都需要提前下载好&#xff0c;然后通过局域网传过去再安装。 另外&#xff0c;软件包可能还依赖其他的库&…

Mac安装tomcat

代码 brew install tomcat 运行结果如下&#xff1a; 如果要启动输入&#xff1a; brew services start tomcat

新书推荐—华为HCIA路由交换技术实战

新书推荐—华为HCIA路由交换技术实战 由HCIE认证讲师、技术能手、ICT大赛优秀指导教师、教学名师、国家规划教材作者联袂编撰&#xff0c;让学习不再是“硬”茬&#xff0c;而是“嗨”起来&#xff01; 《华为HCIA路由交换技术实战》 作者黄君羡组编正月十六工作室书号978-7-12…

半个月获邀请函|在读博士公派新加坡南洋理工大学联合培养

J同学计划先申报CSC联培博士&#xff0c;如若获批&#xff0c;再走本校的联培资助项目。我们仅用半个月时间&#xff0c;就为其申请到新加坡南洋理工大学&#xff0c;因导师接收名额有限制&#xff0c;其又热心推荐了另一位指导导师&#xff0c;最终J同学如愿获得学校资助出国联…

职校老师的工资待遇怎么样

工资水平一直是教师们关注的焦点&#xff0c;毕竟&#xff0c;工资不仅关系到个人的生活品质&#xff0c;还影响着教师的职业满意度和工作动力。职校教师的工资待遇究竟是怎样的呢&#xff1f; 职校教师的工资水平受多种因素影响&#xff0c;包括地区、学校类型、个人资历和教学…

备份服务器的安全风险以及如何通过TDE透明加密提升安全性

备份服务器的潜在安全风险主要包括以下几个方面&#xff1a; 1. 数据泄露风险&#xff1a; 备份数据可能包含敏感信息&#xff0c;如用户个人信息、商业机密等。如果备份数据未经适当保护&#xff0c;例如存储在不安全的位置或未加密&#xff0c;黑客或未授权的人员可能会获取…

AppInventor2 表格布局的外面的黑框怎么去掉?

问&#xff1a;表格布局的外面的黑框怎么去掉啊&#xff1f; 答&#xff1a;这个黑框是界面设计的布局位置示意&#xff0c;实际 App 测试时并没有框。 来源&#xff1a;AppInventor2 表格布局的外面的黑框怎么去掉&#xff1f; - App应用开发 - 清泛IT社区&#xff0c;为创新…

ELT 同步 MySQL 到 Doris

如何基于 Flink CDC 快速构建 MySQL 到 Doris 的 Streaming ELT 作业&#xff0c;包含整库同步、表结构变更同步和分库分表同步的功能。 本教程的演示都将在 Flink CDC CLI 中进行&#xff0c;无需一行 Java/Scala 代码&#xff0c;也无需安装 IDE。 准备阶段 # 准备一台已经…

vscode中更改 git托管的项目里的文件 不显示在 修改项 changes里面

目录 一、问题 二、原因及解决方法 三、总结 tiips:如嫌繁琐&#xff0c;直接移步总结即可&#xff01; 一、问题 1.在vscode中修改 从 git拉取下来的代码&#xff0c;本地不显示被修改的文件&#xff1b;文件夹只有最外层显示红色修改图标;但是里面的被修改的文件也没有被…

IO系列(十) -TCP 滑动窗口原理解析

一、摘要 之前在知乎上分享网络编程知识文章的时候&#xff0c;有个网友私信给我留言了一条“能不能写一篇关于 TCP 滑动窗口原理的文章”。 当时没有立即回复&#xff0c;经过查询多方资料&#xff0c;发现这个 TCP 真的非常非常的复杂&#xff0c;就像一个清澈的小沟&#…

怎么将3D模型转换立面图---模大狮模型网

在建筑设计、室内设计以及产品建模等领域&#xff0c;经常需要将3D模型转换为立面图以进行展示、分析或交流。立面图能够清晰地呈现物体的外观和结构&#xff0c;是设计和施工中不可或缺的一部分。 一、导出3D模型 首先&#xff0c;需要将3D模型导出为CAD软件能够识别的格式。…

第十九节:带你梳理Vue2: 父组件向子组件传参(props传参)

1. 组件嵌套 1.1 组件的嵌套使用 之前有说过,Vue组件跟Vue实例是一样的,因此在Vue中一个组件中也可以定义并使用自己的局部组件,这就是组件的嵌套使用 例如:示例代码如下: <div id"app"><!-- 3. 使用组件 --><my-component></my-component&…

29-ESP32-S3-WIFI_Driver-00 STA模式扫描全部 AP

ESP32-S3 WIFI_Driver 引言 ESP32-S3是一款集成了Wi-Fi和蓝牙功能的芯片。关于WIFI的部分&#xff0c;其实内容比我想象的要多得多。所以通常来说&#xff0c;如果你想要编写自己的Wi-Fi应用程序&#xff0c;最快捷的方法就是先找一个类似的示例应用&#xff0c;然后将它的相…

VSCODE常用插件记录

重点提名&#xff1a; back & ForthBookmarksC/ChighlightSSH FS //SSH插件

JVM之垃圾判断的详细解析

垃圾判断 垃圾介绍 垃圾&#xff1a;如果一个或多个对象没有任何的引用指向它了&#xff0c;那么这个对象现在就是垃圾 作用&#xff1a;释放没用的对象&#xff0c;清除内存里的记录碎片&#xff0c;碎片整理将所占用的堆内存移到堆的一端&#xff0c;以便 JVM 将整理出的内…

第3章 数据链路层

王道学习 考纲内容 &#xff08;一&#xff09;数据链路层的功能 &#xff08;二&#xff09;组帧 &#xff08;三&#xff09;差错控制 检错编码&#xff1b;纠错编码 &#xff08;四&#xff09;流量控制与可靠传输机制 流量控制、可靠传输与滑动窗口…

AcWing 1600:完全二叉树

【题目来源】https://www.acwing.com/problem/content/1602/【题目描述】 给定一个树&#xff0c;请你判断它是否是完全二叉树。【输入格式】 第一行包含整数 N&#xff0c;表示树的结点个数。 树的结点编号为 0∼N−1。 接下来 N 行&#xff0c;每行对应一个结点&#xff0c;并…