当前位置: 首页 > news >正文

【数据结构】图论基础

在这里插入图片描述

文章目录

  • 图的概念
    • 图的基本概念
    • 图的类型
    • 图的表示方法
  • 图的相关基本概念
    • 1. 路径(Path)
    • 2. 连通性(Connectivity)
    • 3. 图的度(Degree)
    • 4. 子图(Subgraph)
    • 5. 生成树(Spanning Tree)
    • 6. 二分图(Bipartite Graph)
    • 7. 拓扑排序(Topological Sort)
    • 8. 欧拉图和哈密顿图
  • 实现图
    • 邻接矩阵实现图
      • 邻接矩阵的基本框架
      • 核心接口
    • 邻接表实现图
      • 邻接表实现图的基本框架
      • 核心接口
  • 总结

图的概念

图(Graph)是离散数学中的一种重要数据结构,用于描述对象(称为顶点,或节点)之间的关系(称为)。图可以表示各种事物之间的连接关系,比如网络中的路由器、社交网络中的用户、城市之间的道路等。

图的基本概念

  1. 顶点(Vertex)

    • 图中的基本单位,也称为节点(Node)。一个图通常由若干个顶点组成,用来表示实体或对象。
  2. 边(Edge)

    • 顶点之间的连接关系称为边。边可以是有方向的(有向图)或无方向的(无向图)。在无向图中,边表示双向关系;在有向图中,边表示单向关系。
  3. 有向图(Directed Graph, Digraph)

    • 在有向图中,边是有方向的,表示从一个顶点指向另一个顶点的单向连接。通常用有向边表示诸如“影响”或“依赖”的关系。
      在这里插入图片描述
  4. 无向图(Undirected Graph)

    • 无向图中的边没有方向,表示两个顶点之间的对称关系,如“相邻”或“连接”。
      在这里插入图片描述
  5. 邻接(Adjacency)

    • 如果两个顶点之间有一条边连接,这两个顶点称为邻接的。
  6. 度(Degree)

    • 一个顶点的度是连接到该顶点的边的数目。在有向图中,区分入度(In-degree)出度(Out-degree),分别表示进入该顶点和从该顶点发出的边的数量。

图的类型

  1. 稀疏图(Sparse Graph)

    • 边的数量远远少于顶点数量的平方(E << V²),大部分顶点之间没有边连接。
  2. 稠密图(Dense Graph)

    • 边的数量接近顶点数量的平方(E ≈ V²),大多数顶点之间有边连接。
  3. 加权图(Weighted Graph)

    • 图中的每条边带有一个权重,用来表示顶点之间的某种度量,如距离、成本或容量。
  4. 连通图(Connected Graph)

    • 对于无向图,若任意两个顶点之间都有路径相连,则称为连通图。有向图中则需区分强连通弱连通
  5. 简单图(Simple Graph)

    • 不包含自环和多重边的图。自环是指从顶点到自身的边,多重边是指两个顶点之间存在多条边。
  6. 完全图(Complete Graph)

    • 图中任意两个顶点之间都有边相连,通常表示为 K n K_n Kn,其中 n n n 是顶点数。

图的表示方法

  1. 邻接矩阵(Adjacency Matrix)

    • 使用一个二维矩阵来表示顶点之间的连接关系,矩阵中的元素表示边的存在性或权重。
  2. 邻接表(Adjacency List)

    • 对每个顶点,维护一个链表(或数组)来存储与之相邻的顶点列表,适合稀疏图。
  3. 边集列表(Edge List)

    • 直接列出图中所有的边,用边的起点和终点来描述,适合图的遍历或算法中的具体操作。

图的相关基本概念

在理解图的结构和操作时,有一些与图密切相关的概念有助于更好地分析和处理图的算法和应用。

1. 路径(Path)

路径是在图中从一个顶点到另一个顶点的行进序列,它由一系列边和顶点组成。根据图的类型和要求,路径可以分为几类:

  • 简单路径(Simple Path):路径中的顶点不重复出现。
  • 回路(Cycle):路径的起点和终点是同一个顶点,且路径中的其他顶点不重复。
    在这里插入图片描述

2. 连通性(Connectivity)

图的连通性描述了图中顶点与顶点之间的可达性。

  • 连通图(Connected Graph):对于无向图,如果从任意一个顶点能到达其他所有顶点,则图是连通的。
  • 强连通图(Strongly Connected Graph):对于有向图,如果任意两个顶点之间都有路径相通,则图是强连通的。
  • 弱连通图(Weakly Connected Graph):对于有向图,如果将其所有边看作无向边,能够使整个图连通,则图是弱连通的。
    在这里插入图片描述

3. 图的度(Degree)

图中一个顶点的度表示与该顶点连接的边的数量。

  • 入度(In-degree):有向图中指向该顶点的边的数量。
  • 出度(Out-degree):有向图中从该顶点发出的边的数量。
    在这里插入图片描述

4. 子图(Subgraph)

子图是从原始图中选取部分顶点和边构成的图。常见的子图类型包括:

  • 生成子图(Spanning Subgraph):包含图的所有顶点,但边可能有所删减。
  • 诱导子图(Induced Subgraph):包含图中某些顶点及这些顶点之间的所有边。
    在这里插入图片描述

5. 生成树(Spanning Tree)

生成树是无向图的一个子图,包含图中的所有顶点,且是一个树形结构(无环、连通)。

  • 最小生成树(Minimum Spanning Tree, MST):在加权图中,生成树的边权和最小的生成树。

生成树:
在这里插入图片描述
最小生成树:
在这里插入图片描述

6. 二分图(Bipartite Graph)

二分图是一种特殊的图,可以将顶点集合分为两个不相交的子集,且所有边都连接两个不同子集中的顶点,而子集中没有内部连接。
在这里插入图片描述

7. 拓扑排序(Topological Sort)

对于有向无环图(DAG),拓扑排序是一种将顶点按依赖关系线性排序的算法,通常用于解决调度、依赖管理等问题。

8. 欧拉图和哈密顿图

  • 欧拉路径(Eulerian Path):经过图中每条边一次且仅一次的路径。如果这样的路径是闭合的,即路径的起点和终点相同,则称为欧拉回路(Eulerian Circuit)
  • 哈密顿路径(Hamiltonian Path):经过图中每个顶点一次且仅一次的路径。如果这样的路径是闭合的,则称为哈密顿回路(Hamiltonian Circuit)

实现图

邻接矩阵实现图

在这里插入图片描述
如果是无向图的话,那么邻接矩阵就是沿着对角线对称的。
在这里插入图片描述
如果是无向图的话,那么就可以通过压缩只存储一半。
除了需要一个存储权值的邻接矩阵我们还需要一个vector来存储顶点,如果涉及到邻接矩阵,那么就会涉及到下标,所以我们应该还需要一个顶点映射下标的map。

邻接矩阵的基本框架

	//         顶点     weight                       有向图/无向图   template<class V, class W, W MAX_W = INT_MAX, bool Direction = false>class Graph{public:private:vector<V> _vertexs;         //顶点集合map<V, int> _indexMap;      //顶点对应下标的关系(顶点---->下标)vector<vector<W>> _matrix;  //邻接矩阵};
}

核心接口

初始化

Graph(const V* a, size_t n)
{// 开辟n个空间_vertexs.resize(n);for (size_t i = 0;i < n;i++){_vertexs[i] = a[i];//顶点----->下标_indexMap[a[i]] = i;}_matrix.resize(n);//权值用MAX_W初始化for (size_t i = 0;i < n;i++) _matrix[i].resize(n, MAX_W);
}

获取顶点的下标

size_t GetVertexIndex(const V& v)
{auto it = _indexMap.find(v);if (it != _indexMap.end()) return it->second;else{// 抛异常出去throw invalid_argument("顶点不存在");// 过编译器逻辑return -1;}
}

通过map的接口find找到v对应的下标,如果it为end(),说明没有这个顶点,直接抛异常,如果存在,则返回对应的下标
添加边

//                   原点        目标点       权值
void AddEdge(const V& src, const V& dst, const W& w)
{// 获取原点下标size_t srci = GetVertexIndex(src);size_t dsti = GetVertexIndex(dst);_matrix[srci][dsti] = w;// 无向图添加两个权值if (Direction == false) _matrix[dsti][srci] = w;
}

找到原点和目标点对应的下标,如果是有向图的话,只需要添加原点到目标点的边,如果是无向图的话,就需要反向添加一下目标点到原点的边了。

邻接表实现图

邻接表是图的一种存储表示方法,常用于存储稀疏图(即边数相对较少的图)。它通过每个顶点对应一个链表或数组来记录与其相邻的顶点。邻接表的空间复杂度相对较小,适合存储大规模图。
在这里插入图片描述
对于无向图来说不存在入度和出度的概念,所以只需要一个邻接表表示,下标的邻接表就是用来表示边的集合。
在这里插入图片描述
拿第一个点为例,这里使用一个结构体来维护的,这个结构体中有指向一下下一个边集的指针,还有一个权值和目标点的下标。
我们说形象一点:
在这里插入图片描述

类似于哈希桶的那个做法

邻接表实现图的基本框架

template<class W>
struct Edge
{int _dsti;  //目标点的下标W _w;       //权值Edge<W>* _next;Edge(int dsti,const W& w):_dsti(dsti),_w(w),_next(nullptr){}
};
//         顶点   weight         有向图/无向图   
template<class V, class W,bool Direction = false>
class Graph
{typedef Edge<W> Edge;
public:private:vector<V> _vertexs;         //顶点集合map<V, int> _indexMap;      //顶点对应下标的关系(顶点---->下标)vector<Edge*> _tables;       //邻接表
};

核心接口

初始化

Graph(const V* a, size_t n)
{// 开辟n个空间_vertexs.resize(n);for (size_t i = 0;i < n;i++){_vertexs[i] = a[i];//顶点----->下标_indexMap[a[i]] = i;}_tables.resize(n,nullptr);//给tables开辟n个空间(n个顶点)
}

获取顶点对应下标

size_t GetVertexIndex(const V& v)
{auto it = _indexMap.find(v);if (it != _indexMap.end()) return it->second;else{// 抛异常出去throw invalid_argument("顶点不存在");// 过编译器逻辑return -1;}
}

添加边

void AddEdge(const V& src, const V& dst, const W& w)
{// 获取原点下标size_t srci = GetVertexIndex(src);size_t dsti = GetVertexIndex(dst);//1 --> 2//原点到目标的权值Edge* eg = new Edge(dsti, w);//这里进行头插eg->_next = _tables[srci];_tables[srci] = eg;//无向图进行特殊处理//2 --> 1if (Direction == false){//反向指向Edge* eg = new Edge(srci, w);eg->_next = _tables[dsti];_tables[dsti] = eg;}
}

这个和邻接矩阵就不一样,邻接表中添加边应该先创建一个对应边的结构体,然后将这个结构体头插到原点对应下标的边集的位置上,如果是无向图的话,需要反向添加一条目标点到原点的边。注意:头插之后需要改变头的位置

总结

通过本篇文章的介绍,我们初步了解了图的基本概念、图的表示方法(如邻接矩阵和邻接表)、以及图中的各种基本性质。图论作为计算机科学和数学中的一个重要分支,其应用范围广泛,从网络设计到路径规划,都有着广泛的应用场景。

在接下来的学习中,我们可以进一步探讨更高级的图算法,如最短路径算法(Dijkstra、Bellman-Ford 等)、图的遍历算法(深度优先搜索、广度优先搜索)、以及图的连通性和最小生成树等高级主题。这些内容将为解决更复杂的实际问题提供坚实的理论基础。

图论的世界广阔而有趣,期待你能在之后的学习和实践中不断挖掘其奥秘!

相关文章:

【数据结构】图论基础

文章目录 图的概念图的基本概念图的类型图的表示方法 图的相关基本概念1. 路径&#xff08;Path&#xff09;2. 连通性&#xff08;Connectivity&#xff09;3. 图的度&#xff08;Degree&#xff09;4. 子图&#xff08;Subgraph&#xff09;5. 生成树&#xff08;Spanning Tr…...

HTML5实现好看的唐朝服饰网站模板源码2

文章目录 1.设计来源1.1 网站首页1.2 唐装演变1.3 唐装配色1.4 唐装花纹1.5 唐装文化 2.效果和源码2.1 动态效果2.2 源代码 源码下载万套模板&#xff0c;程序开发&#xff0c;在线开发&#xff0c;在线沟通 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.ne…...

golang web笔记-2.请求request

什么是request http消息分为request&#xff08;请求&#xff09; 和 response&#xff08;响应&#xff09; request&#xff1a;在go中是一个struct&#xff0c;代表了客户段发送的http请求&#xff0c;已可以通过request 的方法访问请求中的cookie、URL、User Agent&#xf…...

docker的安装与启动——配置国内Docker源

移除旧版本docker sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine 配置docker yum源。 sudo yum install -y yum-utils sudo yum-config-manager –add-repo ht…...

httpsok-v1.17.0-SSL通配符证书自动续签

&#x1f525;httpsok-v1.17.0-SSL通配符证书自动续签 介绍 httpsok 是一个便捷的 HTTPS 证书自动续签工具&#xff0c;基于全新的设计理念&#xff0c;专为 Nginx 、OpenResty 服务器设计。已服务众多中小企业&#xff0c;稳定、安全、可靠。 一行命令&#xff0c;一分钟轻…...

相机、镜头参数详解以及相关计算公式

一、工业相机参数 1、分辨率 相机每次采集图像的像素点数&#xff0c;也是指这个相机总共有多少个感光晶片。在采集图像时&#xff0c;相机的分辨率对检测精度有很大的影响&#xff0c;在对同样打的视场成像时&#xff0c;分辨率越高&#xff0c;对细节的展示越明显。 相机像素…...

【微服务】组件、基础工程构建(day2)

组件 服务注册和发现 微服务模块中&#xff0c;一般是以集群的方式进行部署的&#xff0c;如果我们调用的时候以硬编码的方式&#xff0c;那么当服务出现问题、服务扩缩容等就需要对代码进行修改&#xff0c;这是非常不好的。所以微服务模块中就出现了服务注册和发现组件&…...

ESP32微信小程序SmartConfig配网

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 ESP32&微信小程序SmartConfig配网 前言一、SmartConfig是什么&#xff1f;二、使用乐鑫官方的smart_config例子1.运行照片 三、微信小程序总结 前言 本人是酷爱ESP32S3这…...

【PostgreSQL】提高篇——深入了解不同类型的 JOIN(INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL JOIN)应用操作

1. JOIN 的基础概念 在 SQL 中&#xff0c;JOIN 是用于从两个或多个表中组合行的操作。JOIN 允许我们根据某些条件将表中的数据关联在一起。常见的 JOIN 类型包括&#xff1a; INNER JOIN&#xff1a;仅返回两个表中满足连接条件的行。LEFT JOIN&#xff08;或 LEFT OUTER JO…...

师生健康信息管理:SpringBoot技术突破

第4章 系统设计 4.1 系统体系结构 师生健康信息管理系统的结构图4-1所示&#xff1a; 图4-1 系统结构 登录系统结构图&#xff0c;如图4-2所示&#xff1a; 图4-2 登录结构图 师生健康信息管理系统结构图&#xff0c;如图4-3所示。 图4-3 师生健康信息管理系统结构图 4.2…...

【完-网络安全】Windows注册表

文章目录 注册表启动项及常见作用五个根节点常见入侵方式 注册表 注册表在windows系统的配置和控制方面扮演了一个非常关键的角色&#xff0c;它既是系统全局设置的存储仓库&#xff0c;也是每个用户的设置信息的存储仓库。 启动项及常见作用 快捷键 WinR打开运行窗口&#x…...

车辆重识别(2021NIPS在图像合成方面,扩散模型打败了gans网络)论文阅读2024/10/01

本文在架构方面的创新&#xff1a; ①增加注意头数量&#xff1a; 使用32⇥32、16⇥16和8⇥8分辨率的注意力&#xff0c;而不是只使用16⇥16 ②使用BigGAN残差块 使用Big GAN残差块对激活进行上采样和下采样 ③自适应组归一化层 将经过组归一化操作后的时间步和类嵌入到每…...

掌控物体运动艺术:图扑 Easing 函数实践应用

现如今&#xff0c;前端开发除了构建功能性的网站和应用程序外&#xff0c;还需要创建具有吸引力且尤为流畅交互的用户界面&#xff0c;其中动画技术在其中发挥着至关重要的作用。在数字孪生领域&#xff0c;动画的应用显得尤为重要。数字孪生技术通过精确模拟现实世界中的对象…...

Python从入门到高手4.2节-掌握循环控制语句

目录 4.2.1 理解循环控制 4.2.2 for循环结构 4.2.3 循环结构的else语句 4.2.4 while循环结构 4.2.5 循环结构可以嵌套 4.2.6 国庆节吃好玩好 4.2.1 理解循环控制 我们先来搞清楚循环的含义。以下内容引自汉语词典: 循环意指往复回旋&#xff0c;指事物周而复始地运动或变…...

CSS 中的overscroll-behavior属性

overscroll-behavior 是 CSS 中的一个属性&#xff0c;它用于控制元素在发生滚动时&#xff0c;当滚动范围超出其边界时的行为。这个属性对于改善用户体验特别有用&#xff0c;尤其是在移动端设备上&#xff0c;当用户尝试滚动一个已经达到滚动极限的元素时&#xff0c;可以通过…...

GPT对话知识库——在STM32的平台下,通过SPI读取和写入Flash的步骤。

目录 1&#xff0c;问&#xff1a; 1&#xff0c;答&#xff1a; 步骤概述 步骤 1&#xff1a;SPI 初始化 步骤 2&#xff1a;Flash 初始化&#xff08;可选&#xff09; 步骤 3&#xff1a;发送读取命令 示例&#xff1a;发送读取数据命令 步骤 4&#xff1a;读取数据…...

Pytorch基本知识

model.state_dict()、model.parameters()和model.named_parameters()的区别 parameters()只包含模块的参数,即weight和bias(包括BN的)。 named_parameters()返回包含模块名和模块的参数的列表,列表的每个元素均是包含layer name和layer param的元组。layer param就是param…...

vue3使用Teleport 控制台报警告:Invalid Teleport target on mount: null (object)

Failed to locate Teleport target with selector “.demon”. Note the target element must exist before the component is mounted - i.e. the target cannot be rendered by the component itself, and ideally should be outside of the entire Vue component tree main.…...

使用产品前的环境搭建

对于想学习编程的朋友们&#xff0c;使用本产品解决日常功能需求的同时会对自己编程能力具有较大帮助和提升。 目录 环境搭建 前言&#xff1a; 安装python 安装vscode 下载安装Anaconda 通过conda配置python环境 创建虚拟环境 查看环境是否创建成功 激活环境 安装pyt…...

JAVA基础语法 day07

一、final关键字 1.1final的基础知识 用来修饰类&#xff0c;方法&#xff0c;变量 final修饰类&#xff0c;该类被称为终极类&#xff0c;不能被继承了 final修饰方法&#xff0c;该方法称为终极方法&#xff0c;不能被重写了 final修饰变量&#xff0c;该变量仅能被赋值…...

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…...

Nuxt.js 中的路由配置详解

Nuxt.js 通过其内置的路由系统简化了应用的路由配置&#xff0c;使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

Yolov8 目标检测蒸馏学习记录

yolov8系列模型蒸馏基本流程&#xff0c;代码下载&#xff1a;这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中&#xff0c;**知识蒸馏&#xff08;Knowledge Distillation&#xff09;**被广泛应用&#xff0c;作为提升模型…...

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要&#xff1a; 近期&#xff0c;在使用较新版本的OpenSSH客户端连接老旧SSH服务器时&#xff0c;会遇到 "no matching key exchange method found"​, "n…...

【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制

使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下&#xff0c;限制某个 IP 的访问频率是非常重要的&#xff0c;可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案&#xff0c;使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...

提升移动端网页调试效率:WebDebugX 与常见工具组合实践

在日常移动端开发中&#xff0c;网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时&#xff0c;开发者迫切需要一套高效、可靠且跨平台的调试方案。过去&#xff0c;我们或多或少使用过 Chrome DevTools、Remote Debug…...

Android写一个捕获全局异常的工具类

项目开发和实际运行过程中难免会遇到异常发生&#xff0c;系统提供了一个可以捕获全局异常的工具Uncaughtexceptionhandler&#xff0c;它是Thread的子类&#xff08;就是package java.lang;里线程的Thread&#xff09;。本文将利用它将设备信息、报错信息以及错误的发生时间都…...

验证redis数据结构

一、功能验证 1.验证redis的数据结构&#xff08;如字符串、列表、哈希、集合、有序集合等&#xff09;是否按照预期工作。 2、常见的数据结构验证方法&#xff1a; ①字符串&#xff08;string&#xff09; 测试基本操作 set、get、incr、decr 验证字符串的长度和内容是否正…...

【题解-洛谷】P10480 可达性统计

题目&#xff1a;P10480 可达性统计 题目描述 给定一张 N N N 个点 M M M 条边的有向无环图&#xff0c;分别统计从每个点出发能够到达的点的数量。 输入格式 第一行两个整数 N , M N,M N,M&#xff0c;接下来 M M M 行每行两个整数 x , y x,y x,y&#xff0c;表示从 …...