数据结构(十)图

文章目录

  • 图的简介
    • 图的定义
    • 图的结构
    • 图的分类
      • 无向图
      • 有向图
      • 带权图(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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

电脑录屏怎么录?7个电脑录屏软件免费版强势来袭,赶快收藏!

电脑录屏怎么录&#xff1f;相信很多小伙伴们都不知道怎么在Windows电脑上录屏吧&#xff1f;在当今社会&#xff0c;随着互联网的快速发展&#xff0c;越来越多的小伙伴们开始通过制作视频内容来分享知识、展示技能或者记录生活。电脑录屏成为了一种简单高效的方式&#xff0c…

RocketMQ .NET

RocketMQ 是一款由阿里巴巴集团开发并开源给Apache软件基金会的分布式消息及流处理平台。以其高吞吐量、低延迟、高可用性等特点而广受欢迎。支持Java&#xff0c;C, Python, Go, .NET等。 异步解耦&#xff1a;可以实现上游和下游业务系统的松耦合设计&#xff0c;使得服务部…

markdown语法保存

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

React(四)memo、useCallback、useMemo Hook

目录 (一)memo API 1.先想一个情景 2.用法 (1)props传入普通数据类型的情况 (2)props传入对象的情况 (3)props传入函数的情况 (4)使用自定义比较函数 3.什么时候使用memo&#xff1f; (二)useMemo Hook 1.用法 2.useMemo实现组件记忆化 3.useMemo实现函数记忆化 …

dbserver 软件 展示 全部模式库

目录 1 问题2 实现 1 问题 dbserver 软件 展示 全部模式库 2 实现 以上就可以了

Vue——事件修饰符

文章目录 前言阻止默认事件 prevent阻止事件冒泡 stop 前言 在官方文档中对于事件修饰符有一个很好的说明&#xff0c;本篇文章主要记录验证测试的案例。 官方文档 事件修饰符 阻止默认事件 prevent 在js原生的语言中&#xff0c;可以根据标签本身的事件对象进行阻止默认事件…

从零到一建设数据中台 - 数据可视化

从零到一建设数据中台(八)- 数据可视化 一、数据可视化大屏 数据可视化是借助于图形化手段,清晰有效地传达与沟通信息。 将一些业务的关键指标通过数据可视化的方式展示到一块或多块LED大屏上,以大屏为主要展示载体的数据可视化设计。 在数据可视化大屏构建过程中,为了…

对红黑树、跳表、B+树的一些理解

文章目录 红黑树应用场景 跳表使用场景 B树使用场景 毫无疑问数据结构是复杂的&#xff0c;让人头大的&#xff0c;大学时唯一挂科的就是数据结构&#xff0c;上学时不用心&#xff0c;不晓得自己的职业生涯要一直被数据结构支配。 或多或少&#xff0c;面试抱佛脚时&#xff0…

如何做好投入式水位计的安装与维护

投入式水位计是一种广泛应用于各种环境和水位监测场景的精确测量设备。为了确保其长期稳定运行和测量准确性&#xff0c;正确的安装和维护至关重要。本文将详细介绍投入式水位计的安装步骤和注意事项&#xff0c;以及维护过程中的关键要点。 一、投入式水位计的安装 准备工作&a…

探索AI去衣技术中的反射应用

在当今数字时代&#xff0c;人工智能&#xff08;AI&#xff09;技术的飞速发展已经渗透到了我们生活的方方面面。其中&#xff0c;图像处理和计算机视觉作为AI的重要分支&#xff0c;正不断推动着创新应用的边界。今天&#xff0c;我们要探讨的是一个颇具争议但又技术上颇为有…

【2024最新华为OD-C卷试题汇总】披萨大作战 (100分) - 支持在线评测+三语言AC题解(Python/Java/Cpp)

&#x1f36d; 大家好这里是清隆学长 &#xff0c;一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C卷的三语言AC题解 &#x1f4bb; ACM银牌&#x1f948;| 多次AK大厂笔试 &#xff5c; 编程一对一辅导 &#x1f44f; 感谢大家的订阅➕ 和 喜欢&#x1f497; 文章目录 前…

若依+vue框架使用字典下拉框回显错误

【版权所有&#xff0c;文章允许转载&#xff0c;但须以链接方式注明源地址&#xff0c;否则追究法律责任】【创作不易&#xff0c;点个赞就是对我最大的支持】 前言 仅作为学习笔记&#xff0c;供大家参考 总结的不错的话&#xff0c;记得点赞收藏关注哦&#xff01; 目录 …

面试:eureka、nacos、consul的区别

配置中心 配置中心eureka不支持nacos支持 用起来简单&#xff0c;符合springBoot的命名风格&#xff0c;支持动态刷新consul支持 但用起来偏麻烦&#xff0c;不太符合springBoot框架的命名风格&#xff0c;支持动态刷新 注册中心

电流继电器DL-13 柜内安装带板前接线附件 JOSEF约瑟

DL-10系列电流继电器板前接线为电磁式瞬动过电流继电器&#xff0c;它广泛用于电力系统二次回路继电保护装置线路中&#xff0c;作为过电流启动元件。 系列型号 DL-11电流继电器; DL-12电流继电器; DL-13电流继电器&#xff1b; 一、应用范围 DL-13/2电流继电器 板前接线为…

一文看懂!电磁仿真软件CST Studio Suite的技术发展历程

CST工作套件室是一款功能强大、专业级别的软件包&#xff0c;用于进行微波无源器件和天线的仿真分析和设计。它支持的应用领域包括耦合器、滤波器、环流器、隔离器、谐振腔、平面结构、连接器、电磁兼容、集成电路封装以及各种类型的天线和天线阵列。该软件可以提供必要的S参数…

polarctf靶场[reverse]shell、PE结构、拼接

[reverse]shell 考点&#xff1a;脱壳 将所解压的文件拖入DIE有无有壳&#xff0c;文件类型 发现有UPX壳&#xff0c;是32位的文件&#xff0c;先脱壳 用FFI工具脱壳 将脱壳后的程序用32位IDA进行反汇编 点开_main_0函数进行查看 看到flag&#xff0c;&#xff08;F5&#…

开源DMS文档管理系统 Nuxeo Vs Alfresco对比及 API 使用概述

1. 文档管理系统是什么 文档管理系统&#xff08;DMS&#xff1a;Document Management System&#xff09;是一种软件系统&#xff0c;用于组织、存储、检索和管理电子文档和文件。这些文件可以是各种格式的电子文档&#xff0c;如文本文档、电子表格、图像、音频或视频文件等…

Vue3实战笔记(50)—Vue 3+ECharts还能看股票?附源码

文章目录 前言一、改进之前的封装echarts组件二、封装股票k线图总结 前言 今天封装股票k线图组件 前几天学的几个知识点都有用到&#xff0c;都是在封装k线图的时候遇到的问题&#xff0c;又啃了一遍基础。 一、改进之前的封装echarts组件 使用ref对象方式封装useEChartsRef.t…

端到端目标检测 |从DETR 到 GroundingDINO

文章目录 一&#xff0c;DETR1. 简介2. 亮点3. 细节4. 总结一下 二&#xff0c;GroundingDINOGrounding DINO的整体流程Grounding DINO的目标函数 一&#xff0c;DETR 之前的目标检测框架&#xff0c;需要很多的人工干预&#xff0c;很多的先验知识&#xff0c;而且可能还需要…

从简单到复杂,红酒配餐的层次感与变化

红酒配餐是一种艺术&#xff0c;通过不同层次的搭配&#xff0c;可以呈现出丰富的味觉变化&#xff0c;使每一口都充满惊喜。云仓酒庄雷盛红酒以其卓着的品质和与众不同的口感&#xff0c;为红酒配餐提供了无限可能。从简单到复杂&#xff0c;红酒配餐的层次感与变化如下&#…