图结构基本知识
图
- 1. 相关概念
- 2. 图的表示方式
- 3. 图的遍历
- 3.1 深度优先遍历(DFS)
- 3.2 广度优先遍历(BFS)
1. 相关概念
- 图G(V,E) :一种数据结构,可表示“多对多”关系,由顶点集V和边集E组成;
- 顶点(vertex) :
- 边 (edge):一幅点对(v,w),v,w∈V,边也称为弧;
- 邻接:点v,w邻接,当且仅当边(v,w)∈E;
- 路径 :由一个顶点序列v1,v2,…,vn组成,路径长为n-1;
- 有向图 :边是单向的,点对有序;
- 无向图 :边是双向的图,点对无序;
- 带权图:不同边具有不同的权值的图;
- 连通:无向图的一个顶点到其他任何顶点都存在一条路径,则称其为连通的;
- 强连通:有向图的一个顶点到其他任何顶点都存在一条路径;
- 弱连通:有向图本身不是强连通的,但是其边不考虑方向的无向图是连通的;
- 完全图:每一对顶点间都存在边;
2. 图的表示方式
- 邻接矩阵:使用二维数组实现,数组中每个元素表示图中两顶点之间是否有边,或者表示边的权值,适用于稠密图,对于稀疏图而言此表示方法过于浪费空间;

package com.northsmile.graph;import java.util.ArrayList;
import java.util.Arrays;/*** Author:NorthSmile* Create:2023/4/18 9:17* 使用邻接矩阵表示图(无向图)*/
public class Graph {// 存储边及其权值int[][] edges;// 存储顶点ArrayList<String> vertexes;// 记录边的数目int edgeNums;public Graph(int n){edges=new int[n][n];vertexes=new ArrayList<>(n);edgeNums=0;}/*** 插入顶点* @param vertex*/public void insertVertex(String vertex){vertexes.add(vertex);}/*** 插入边* @param v1 边的一个顶点对应下标* @param v2 边的另一个顶点对应下标* @param w 边对应权值,默认为1*/public void insertEdge(int v1,int v2,int w){edges[v1][v2]=w;edges[v2][v1]=w;edgeNums++;}/*** 获取顶点数量* @return*/public int getVertexesNum(){return vertexes.size();}/*** 获取边的数目* @return*/public int getEdgesNum(){return edgeNums;}/*** 获取指定下标对应的顶点的值* @param v* @return*/public String getValByIndex(int v){return vertexes.get(v);}/*** 获取指定边的权值* @param v1* @param v2* @return*/public int getWeightOfEdge(int v1,int v2){return edges[v1][v2];}/*** 显示表示图的邻接矩阵*/public void showGraph(){for (int[] edge:edges){System.out.println(Arrays.toString(edge));}}
}
package com.northsmile.graph;/*** Author:NorthSmile* Create:2023/4/18 9:18*/
public class GraphDemo {public static void main(String[] args) {int n=5;String[] vertexes={"A","B","C","D","E"};Graph graph = new Graph(n);// 插入顶点for (String vertex:vertexes){graph.insertVertex(vertex);}// 插入边graph.insertEdge(0,1,1);graph.insertEdge(0,2,1);graph.insertEdge(1,2,1);graph.insertEdge(1,3,1);graph.insertEdge(1,4,1);graph.showGraph();}
}
- 邻接表:使用数组+链表的方式实现,适用于稀疏图表示,是图的标准表示方法,对于每个顶点,将其所有邻接点使用一个表存放;

package com.northsmile.graph;import java.util.ArrayList;
import java.util.HashMap;/*** Author:NorthSmile* Create:2023/4/18 11:12* 使用邻接表表示图(有向图)*/
public class GraphByAdjacenceList {// 邻接表HashMap<String,Vertex> list;int vertexNums;int edgeNums;public GraphByAdjacenceList(int n){list=new HashMap<>();vertexNums=n;edgeNums=0;}/*** 插入顶点* @param vertex*/public void insertVertex(String vertex){list.put(vertex,new Vertex(vertexNums));}/*** 插入边* @param v 顶点* @param w 邻接点*/public void insertEdge(String v,String w){Vertex vertex = list.get(v);vertex.table.add(w);edgeNums++;}/*** 获取顶点数量* @return*/public int getVertexesNum(){return list.size();}/*** 获取边的数目* @return*/public int getEdgesNum(){return edgeNums;}/*** 显示表示图的邻接表*/public void showGraph(){for (String vertex:list.keySet()){System.out.println(vertex+":"+list.get(vertex).table);}}/*** 顶点类*/class Vertex{ArrayList<String> table;public Vertex(int n){table=new ArrayList<>(n/2);}}
}
package com.northsmile.graph;/*** Author:NorthSmile* Create:2023/4/18 9:18*/
public class GraphDemo {public static void main(String[] args) {// 2.邻接表int n=5;String[] vertexes={"A","B","C","D","E"};GraphByAdjacenceList graph = new GraphByAdjacenceList(n);// 插入顶点for (String vertex:vertexes){graph.insertVertex(vertex);}// 插入边graph.insertEdge("A","B");graph.insertEdge("A","C");graph.insertEdge("B","C");graph.insertEdge("B","D");graph.insertEdge("B","E");graph.showGraph();}
}
3. 图的遍历

3.1 深度优先遍历(DFS)
- 类似树的先序遍历,先访问当前顶点,再依次以其邻接点为新的起点,进行深度优先遍历;
- 与树的遍历不同,图在深度优先遍历时,当前顶点的邻接点可能已经访问过,所以无需再进行访问;
- 为了实现顶点的唯一遍历,在代码实现时需要提供一个标记数组,表示对应顶点是否已经访问过;
- 代码实现以递归方式进行;


/*** 深度优先遍历:类似树的先序遍历* @param v 以当前点开始遍历* @param visited 标记节点是否访问过*/public void dfs(int v,boolean[] visited){System.out.print(vertexes.get(v)+"->");// 遍历当前顶点的邻接点for (int i=0;i<vertexes.size();i++){// 说明v、i之间存在边if (edges[v][i]!=0&&!visited[i]){visited[i]=true;dfs(i,visited);}}}public void dfs(){// 标记顶点是否已经访问过boolean[] visited=new boolean[vertexes.size()];// 以每个顶点开始进行DFS,实现图的完整遍历for (int i=0;i<vertexes.size();i++){if (!visited[i]){visited[i]=true;dfs(i,visited);}}}
3.2 广度优先遍历(BFS)
- 类似树的层序遍历,先访问当前顶点,再依次访问其邻接点,然后分别以其邻接点为新的起点,继续进行广度优先遍历;
- 与树的遍历不同,图在深度优先遍历时,当前顶点的邻接点可能已经访问过,所以无需再进行访问;
- 为了实现顶点的唯一遍历,在代码实现时需要提供一个标记数组,表示对应顶点是否已经访问过;
- 代码实现借助队列实现;

/*** 广度优先遍历:类似树的层次遍历* @param v 以当前点开始遍历* @param visited 标记节点是否访问过*/public void bfs(int v,boolean[] visited){ArrayDeque<Integer> queue=new ArrayDeque<>();queue.offer(v);visited[v]=true;while (!queue.isEmpty()){Integer cur = queue.poll();System.out.print(vertexes.get(cur)+"->");// 遍历当前顶点的邻接点for (int i=0;i<vertexes.size();i++){// 说明v、i之间存在边if (edges[cur][i]!=0&&!visited[i]){visited[i]=true;queue.offer(i);}}}}public void bfs(){// 标记顶点是否已经访问过boolean[] visited=new boolean[vertexes.size()];// 以每个顶点开始进行BFS,实现图的完整遍历for (int i=0;i<vertexes.size();i++){if (!visited[i]){bfs(i,visited);}}}
资料来源:尚硅谷
相关文章:
图结构基本知识
图 1. 相关概念2. 图的表示方式3. 图的遍历3.1 深度优先遍历(DFS)3.2 广度优先遍历(BFS) 1. 相关概念 图G(V,E) :一种数据结构,可表示“多对多”关系,由顶点集V和边集E组成;顶点(ve…...
Hibernate 的多种查询方式
Hibernate 是一个开源的 ORM(对象关系映射)框架,它可以将 Java 对象映射到数据库表中,实现对象与关系数据库的映射。Hibernate 提供了多种查询方式,包括 OID 检索、对象导航检索、HQL 检索、QBC 检索和 SQL 检索。除此…...
FreeRTOS 任务调度及相关函数详解(一)
文章目录 一、任务调度器开启函数 vTaskStartScheduler()二、内核相关硬件初始化函数 xPortStartScheduler()三、启动第一个任务 prvStartFirstTask()四、中断服务函数 xPortPendSVHandler()五、空闲任务 一、任务调度器开启函数 vTaskStartScheduler() 这个函数的功能就是开启…...
飞桨paddlespeech语音唤醒推理C实现
上篇(飞桨paddlespeech 语音唤醒初探)初探了paddlespeech下的语音唤醒方案,通过调试也搞清楚了里面的细节。因为是python 下的,不能直接部署,要想在嵌入式上部署需要有C下的推理实现,于是我就在C下把这个方…...
04-Mysql常用操作
1. DDL 常见数据库操作 # 查询所有数据库 show databases; # 查询当前数据库 select databases();# 使用数据库 use 数据库名;# 创建数据库 create database [if not exits] 数据库名; # []代表可选可不选# 删除数据库 drop database [if exits] 数据库名; 常见表操作 创建…...
TensorFlow 2 和 Keras 高级深度学习:1~5
原文:Advanced Deep Learning with TensorFlow 2 and Keras 协议:CC BY-NC-SA 4.0 译者:飞龙 本文来自【ApacheCN 深度学习 译文集】,采用译后编辑(MTPE)流程来尽可能提升效率。 不要担心自己的形象&#x…...
UML类图
一、UML 1、什么是UML? UML——Unified modeling language UML(统一建模语言),是一种用于软件系统分析和设计的语言工具,它用于帮助软件开发人员进行思考和记录思路的结果。UML本身是一套符号的规定,就像数学符号和化学符号一样&…...
【Python】【进阶篇】二十六、Python爬虫的Scrapy爬虫框架
目录 二十六、Python爬虫的Scrapy爬虫框架26.1 Scrapy下载安装26.2 创建Scrapy爬虫项目1) 创建第一个Scrapy爬虫项目 26.3 Scrapy爬虫工作流程26.4 settings配置文件 二十六、Python爬虫的Scrapy爬虫框架 Scrapy 是一个基于 Twisted 实现的异步处理爬虫框架,该框架…...
PyTorch 深度学习实用指南:6~8
原文:PyTorch Deep Learning Hands-On 协议:CC BY-NC-SA 4.0 译者:飞龙 本文来自【ApacheCN 深度学习 译文集】,采用译后编辑(MTPE)流程来尽可能提升效率。 不要担心自己的形象,只关心如何实现目…...
数据湖 Hudi 核心概念
文章目录 什么是 Hudi ?Hudi 是如何对数据进行管理的?Hudi 表结构Hudi 核心概念 什么是 Hudi ? Hudi 是一个用于处理大数据湖的开源框架。 大数据湖是指一个大规模的、中心化的数据存储库,其中包含各种类型的数据,如结构化数据、半结构化…...
爬虫请求头Content-Length的计算方法
重点:使用node.js 环境计算,同时要让计算的数据通过JSON.stringify从对象变成string。 1. Blob size var str 中国 new Blob([str]).size // 6 2、Buffer.byteLength # node > var str 中国 undefined > Buffer.byteLength(str, utf8) 6 原文…...
Open Inventor 2023.1 Crack
发行说明 Open Inventor 2023.1(次要版本) 文档于 2023 年 4 月发布。 此版本中包含的增强功能和新功能: Open Inventor 10 版本编号更改体积可视化 单一分辨率的体绘制着色器中与裁剪和 ROI 相关的新功能MeshVizXLM 在 C 中扩展的剪辑线提…...
【华为OD机试真题】查找树中元素(查找二叉树节点)(javaC++python)100%通过率
查找树中元素 知识点树BFSQ搜索广搜 时间限制:1s空间限制:256MB限定语言:不限 题目描述: 已知树形结构的所有节点信息,现要求根据输入坐标(x,y)找到该节点保存的内容 值;其中: x表示节点所在的层数,根节点位于第0层,根节点的子节点位于第1层,依次类推; y表示节…...
常用设计模式
里氏替换原则:子类可以扩展父类的功能,但是不要更改父类的已经实现的方法子类对父类的方法尽量不要重写和重载。(我们可以采用final的手段强制来遵循)创建型模式 单例模式:维护线程数据安全 懒汉式 public class Test{ 饿汉式 private static final Test…...
时序分析 49 -- 贝叶斯时序预测(一)
贝叶斯时序预测(一) 时序预测在统计分析和机器学习领域一直都是一个比较重要的话题。在本系列前面的文章中我们介绍了诸如ARIMA系列方法,Holt-Winter指数平滑模型等多种常用方法,实际上这些看似不同的模型和方法之间都具有千丝万缕…...
从传统管理到智慧水务:数字化转型的挑战与机遇
概念 智慧水务是指利用互联网、物联网、大数据、人工智能等技术手段,将智能化、信息化、互联网等技术与水务领域相结合,通过感知、传输、处理水质、水量、水价等数据信息,对水资源进行全面监测、综合管理、智能调度和优化配置的智能化水务系…...
ROS学习第十八节——launch文件(详细介绍)
1.概述 关于 launch 文件的使用已经不陌生了,之前就曾经介绍到: 一个程序中可能需要启动多个节点,比如:ROS 内置的小乌龟案例,如果要控制乌龟运动,要启动多个窗口,分别启动 roscore、乌龟界面节点、键盘控制节点。如果…...
javaweb在校大学生贷款管理系统ns08a9
1系统主要实现:学生注册、填写详细资料、申请贷款、学校审核、银行审核、贷后管理等功能, (1) 学生注册:学生通过注册用户,提交自己的详细个人资料,考虑现实应用中的安全性,资料提交后不可修改;…...
分布式之搜索解决方案es
一 ES初识 1.1 概述 ElasticSearch:是基于 Lucene 的 Restful 的分布式实时全文搜索引擎,每个字段都被索引并可被搜索,可以快速存储、搜索、分析海量的数据。是ELK的一个组成,是一个产品,而且是非常完善的产品,ELK代表…...
CSDN 编程竞赛四十六期题解
地址:CSDN 编程竞赛四十六期 思路:通过找规律可以知道,在周期第一个位置的数的下标都有一个规律:除以三的余数为 1 。而第二个位置,第三个位置的余数分别为 2 , 0 。 因此可以开一个长度为 3 的总和数组&am…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...
【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...
vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
LangFlow技术架构分析
🔧 LangFlow 的可视化技术栈 前端节点编辑器 底层框架:基于 (一个现代化的 React 节点绘图库) 功能: 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...
springboot 日志类切面,接口成功记录日志,失败不记录
springboot 日志类切面,接口成功记录日志,失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...
数据库——redis
一、Redis 介绍 1. 概述 Redis(Remote Dictionary Server)是一个开源的、高性能的内存键值数据库系统,具有以下核心特点: 内存存储架构:数据主要存储在内存中,提供微秒级的读写响应 多数据结构支持&…...
跨平台商品数据接口的标准化与规范化发展路径:淘宝京东拼多多的最新实践
在电商行业蓬勃发展的当下,多平台运营已成为众多商家的必然选择。然而,不同电商平台在商品数据接口方面存在差异,导致商家在跨平台运营时面临诸多挑战,如数据对接困难、运营效率低下、用户体验不一致等。跨平台商品数据接口的标准…...
