数据结构(十)图

news2024/11/15 11:00:39

文章目录

  • 图的简介
    • 图的定义
    • 图的结构
    • 图的分类
      • 无向图
      • 有向图
      • 带权图(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.coloradmin.cn/o/1714331.html

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

相关文章

ai写作助手有哪些,5款强大的ai写作工具为你所用

在科技日新月异的时代&#xff0c;人工智能已经悄然走进我们的生活&#xff0c;为我们带来了诸多便利。其中&#xff0c;AI写作助手作为一种创新的工具&#xff0c;正在改变着我们的写作方式。它们不仅能够提供创意灵感&#xff0c;还能帮助我们提高写作效率&#xff0c;让文字…

在VSCode 中增加文件与文件夹的可辨识度

今天重新打开VSCode&#xff0c;打算新建一个项目做测试&#xff0c;看到VSCode中的文件与文件夹很不容易辨认&#xff0c;有时候容易导致一些误操作&#xff0c;需要做一些配置来改变。 效果图&#xff1a; 只需要做简单的2步就可以了。 1、安装插件 ⑴ 打开VSCode的扩展搜索并…

由浅入深二叉树刷题指南与讲解

目录 前言二叉树OJ基础题目1. 单值二叉树2. 检查两棵树是否相同3. 二叉树的前中后序遍历4. 另一棵树的子树5. 对称二叉树6. 二叉树的构建以及遍历 二叉树其他方法的实现1. 二叉树的销毁2. 层序遍历3. 判断二叉树是否是完全二叉树 二叉树的其他性质总结 前言 上一篇我们已经了解…

整理三维空间内4点的209个结构

4点的209个结构按照旋转对称的关系可分成73组 如1&#xff0c;72&#xff0c;177为一组, z y x z y x 1 72 177 1 2 10 93 4 * 4 74 39 2 * 3 73 179 5 * 5 76 178 3 * 6 75 133 6 7 77 180 7 8 8 89 34 9 11 95 35 * 35 91 …

编译安装MySQL服务(LAMP2)

目录 1.初始化设置&#xff0c;将安装mysql 所需软件包传到/opt目录下 &#xff08;1&#xff09;关闭防火墙 &#xff08;2&#xff09;上传软件包到/opt目录 2.安装环境依赖包 3.配置软件模块 4.编译及安装 5.创建mysql用户 6.修改mysql 配置文件 7.更改mysql安装目…

AB实验人群定向HTE模型1 - Causal Tree

背景 论文给出基于决策树估计实验对不同用户的不同影响。并提出Honest&#xff0c;variance Penalty算法旨在改进CART在tree growth过程中的过拟合问题。 我们举个例子&#xff1a;科研人员想衡量一种新的降血压药对病人的效果&#xff0c;发现服药的患者有些血压降低但有些血…

APP逆向之调试的开启

很基础的一个功能设置&#xff0c;大佬轻喷。 背景 在开始进行对APP逆向分析的时候&#xff0c;需要对APP打开调试模式。 打开调试的模式有多种方式可以通过直接改包方式也可以通过借助第三方工具进行打开调试模式。 下面就整理下这个打开调试模式的一些方式。 改包修改模…

vue+element-ui时间级联动态表单,新增行,删除行,表单验证

需求背景: 需要实现配置一种时间去执行定时任务,可能是每年一次,每月一次,每周一次,每天一次四种情况,最少配置一条,最多配置五条。年,月,周,日,时分秒是级联关系。点击提交,整体表单校验。 效果图 代码实现,具体看里面的注释 完整代码 <template><e…

elastich运维

Elastichsearch是一种高度可扩展的开源全文搜索和分析引擎&#xff0c;可以用来实现快速、高效的数据检索。 集群规划与部署&#xff1a;首先需要根据业务需求规划Elastichsearch集群的节点数量和角色&#xff08;如主节点、副本节点、协调节点等&#xff09;。在部署时&#x…

深度学习创新点不大但有效果,可以发论文吗?

深度学习中创新点比较小&#xff0c;但有效果&#xff0c;可以发论文吗&#xff1f;当然可以发&#xff0c;但如果想让编辑和审稿人眼前一亮&#xff0c;投中更高区位的论文&#xff0c;写作永远都是重要的。 那么怎样“讲故事”才能让论文更有吸引力&#xff1f;我总结了三点…

QT7_视频知识点笔记_67_项目练习(页面以及对话框的切换,自定义数据类型,DB数据库类的自定义及使用)

视频项目&#xff1a;7----汽车销售管理系统&#xff08;登录&#xff0c;品牌车管理&#xff0c;新车入库&#xff0c;销售统计图表&#xff09;-----项目视频没有&#xff0c;代码也不全&#xff0c;更改项目练习&#xff1a;学生信息管理系统。 学生信息管理系统&#xff1…

智能除螨—wtn6040-8s语音芯片方案引领除螨仪新时代

语音螨仪开发背景&#xff1a; 随着物联网技术的快速发展&#xff0c;除螨仪作为家庭清洁的重要工具&#xff0c;其智能化、人性化的设计成为提升市场竞争力的关键。置入语音芯片的除螨仪&#xff0c;通过开机提示、工作状态反馈、操作指引、故障提醒等内容。用户可以更加直观…

文献解读-群体基因组第二期|《中国人群中PAX2新生突变的检测及表型分析:一项单中心研究》

关键词&#xff1a;应用遗传流行病学&#xff1b;群体测序&#xff1b;群体基因组&#xff1b;基因组变异检测&#xff1b; 文献简介 标题&#xff08;英文&#xff09;&#xff1a;Detection of De Novo PAX2 Variants and Phenotypes in Chinese Population: A Single-Cente…

AI智能分析技术与安防视频融合当前面临的困难与挑战

人工智能与安防视频的融合为现代安全领域带来了革命性的变化&#xff0c;提高了安全管理水平、降低了管理成本并为用户提供了更加便捷和高效的服务。随着技术的不断进步和应用场景的不断拓展&#xff0c;未来人工智能与安防的融合将展现出更加广阔的发展前景。然而&#xff0c;…

Pi 母公司将开发情感 AI 商业机器人;Meta 科学家:Sora 不是视频生成唯一方向丨RTE 开发者日报 Vol.214

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE&#xff08;Real-Time Engagement&#xff09; 领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、「…

不用写采集规则的网页采集软件

传统的网页采集工具采集网页数据&#xff0c;需要查看和研究网页代码&#xff0c;编写复杂繁琐的采集规则&#xff0c;对于有技术基础的人&#xff0c;配置一个采集规则也要花费不少时间&#xff0c;更何况对于不懂技术的普通用户来说&#xff0c;简直是一项不太可能完成的任务…

开源表单流程设计器有哪几个突出的优势特点?

当前&#xff0c;传统的表单制作已经无法满足现在企业的发展需求了。想要实现高效率发展&#xff0c;需要引进先进的低代码技术平台、开源表单流程设计器等优秀软件平台助力发展。它们具有可视化操作界面、灵活好操作、易维护、效率高等诸多优势特点&#xff0c;在推动企业实现…

如何使用 .htaccess 删除文件扩展名

本周有一个客户&#xff0c;购买Hostease的虚拟主机&#xff0c;询问我们的在线客服&#xff0c;如何使用 .htaccess 删除文件扩展名&#xff1f;我们为用户提供相关教程&#xff0c;用户很快解决了遇到的问题。在此&#xff0c;我们分享这个操作教程&#xff0c;希望可以对您有…

Docker化Spring Boot3应用:从镜像构建到部署

随着容器化技术的发展&#xff0c;越来越多的应用采用了容器化部署的方式。容器化部署极大地减少了因部署环境不同带来的差异&#xff0c;实现了一次构建、随处运行的效果。此外&#xff0c;容器化还具有版本管理、快速启动、持续集成等优点。今天&#xff0c;我们将介绍如何在…

【linux】运维-基础知识-认知hahoop周边

1. HDFS HDFS&#xff08;Hadoop Distributed File System&#xff09;–Hadoop分布式文件存储系统 源自于Google的GFS论文&#xff0c;HDFS是GFS的克隆版 HDFS是Hadoop中数据存储和管理的基础 他是一个高容错的系统&#xff0c;能够自动解决硬件故障&#xff0c;eg&#xff1a…