【数据结构】图论基础

在这里插入图片描述

文章目录

  • 图的概念
    • 图的基本概念
    • 图的类型
    • 图的表示方法
  • 图的相关基本概念
    • 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 等)、图的遍历算法(深度优先搜索、广度优先搜索)、以及图的连通性和最小生成树等高级主题。这些内容将为解决更复杂的实际问题提供坚实的理论基础。

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

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

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

相关文章

docker pull 超时Timeout失败的解决办法

当国内开发者docker pull遇到如下提示时&#xff0c;不要惊讶 [rootvm /]# docker pull postgres Using default tag: latest Error response from daemon: Get "https://registry-1.docker.io/v2/": dial tcp 128.121.146.235:443: i/o timeout [rootvm /]# 自2024…

dcatadmin 自定义登录页面

一、问题&#xff1a; 在后台管理系统中&#xff0c;不同的项目想要不同的登录页面&#xff0c;但是框架自带的登录页面就只有一个。 解决&#xff1a; 由芒果系统改造的dcatadmin登录插件&#xff0c;实现一键安装改变登录页面。 项目介绍 基于Laravel和Vue的快速开发的后台管…

c++926

1.什么是虚函数&#xff1f;什么是纯虚函数&#xff1f; 虚函数&#xff1a;被virtual关键字修饰的成员函数&#xff0c;用于实现多态性&#xff0c;通过基类访问派生类的函数。纯虚函数&#xff1a;在虚函数后面添加0&#xff0c;只有声明而没有实现&#xff0c;需要派生类提…

如何使用ssm实现基于HTML的中国传统面食介绍网站的搭建+vue

TOC ssm758基于HTML的中国传统面食介绍网站的搭建vue 第1章 绪论 1.1选题动因 当前的网络技术&#xff0c;软件技术等都具备成熟的理论基础&#xff0c;市场上也出现各种技术开发的软件&#xff0c;这些软件都被用于各个领域&#xff0c;包括生活和工作的领域。随着电脑和笔…

SkyWalking 高可用

生产环境中&#xff0c;后端应用需要支持高吞吐量并且支持高可用来保证服务的稳定&#xff0c;因此需要高可用集群管理。 集群方案 Skywalking集群是将 skywalking oap 作为一个服务注册到nacos上&#xff0c;只要skywalking oap服务没有全部宕机&#xff0c;保证有一个skywal…

electron出现乱码和使用cmd出现乱码

第一种出现乱码。这种可以通过chcp 65001&#xff0c;设置为utf-8的编码。第二种&#xff0c;是执行exec的时候出现乱码&#xff0c;这个时候需要设置一些编码格式&#xff0c;可以通过iconv-lite进行解决&#xff0c;这个方法是node自带的&#xff0c;所以不需要导入。使用方法…

SpringCloud-基于Docker和Docker-Compose的项目部署

一、初始化环境 1. 卸载旧版本 首先&#xff0c;卸载可能已存在的旧版本 Docker。如果您不确定是否安装过&#xff0c;可以直接执行以下命令&#xff1a; sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logro…

openpnp - 底部相机高级校正的参数设置

文章目录 openpnp - 底部相机高级校正的参数设置概述笔记修改 “Radial Lines Per Calibration Z” 的方法不同 “Radial Lines Per Calibration Z”的校验结果不同 “Radial Lines Per Calibration Z”的设备校验动作的比较总结备注END openpnp - 底部相机高级校正的参数设置 …

平面电磁波(解麦克斯韦方程)

注意无源代表你立方程那个点xyzt处没有源&#xff0c;电场磁场也是这个点的。 j电流面密度&#xff0c;电流除以单位面积&#xff0c;ρ电荷体密度&#xff0c;电荷除以单位体积。 j方程组有16个未知数&#xff0c;每个矢量有三个xyz分量&#xff0c;即三个未知数&#xff0c;…

人口普查管理系统基于VUE+SpringBoot+Spring+SpringMVC+MyBatis开发设计与实现

目录 1. 系统概述 2. 系统架构设计 3. 技术实现细节 3.1 前端实现 3.2 后端实现 3.3 数据库设计 4. 安全性设计 5. 效果展示 ​编辑​编辑 6. 测试与部署 7. 示例代码 8. 结论与展望 一个基于 Vue Spring Boot Spring Spring MVC MyBatis 的人口普查管理…

加密与安全_TOTP 一次性密码生成算法

文章目录 PreTOTP是什么TOTP 算法工作原理TOTP 生成公式TOTP 与 HOTP 的对比Code生成TOTP验证 TOTP使用场景小结 TOTP 与 HOTP 的主要区别TOTP 与 HOTP应用场景比较TOTP 与 HOTP安全性分析 Pre 加密与安全_HTOP 一次性密码生成算法 https://github.com/samdjstevens/java-tot…

微信小程序服务端API安全鉴权统一调用封装

目录 一、序言二、前置准备1、获取小程序AppID和AppSecret2、下载对称加密密钥3、下载加签私钥4、下载验签证书 三、加解密封装1、相关基础类2、加解密工具类 四、HTTP调用封装五、微信服务端API网关调用封装1、基础类2、属性类和工具类3、枚举类4、网关核心调用抽象类5、网关核…

毕业论文设计javaweb+VUE高校教师信息管理系统

目录 一、系统概述 二、功能详解 1. 教师管理 2. 部门管理 3. 奖惩管理 4. 业绩管理 5. 培训管理 6. 报表查询 三、总结 四、示例代码 1 前端VUE 2 后端SpringBootjava 3 数据库表 随着教育信息化的发展&#xff0c;传统的手工管理方式已经不能满足现代学校对教师…

自动驾驶系列—自动驾驶发展史介绍

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

PyCharm开发工具的安装和基础使用

打开官网&#xff1a;https://www.jetbrains.com/ 切换中文语言&#xff0c; 点击开发者工具 → 选择PyCharm&#xff0c; 点击下载&#xff0c; 初学者下载免费使用的社区版&#xff08;community&#xff09;就够了&#xff0c; 点击下载&#xff0c; 点击下一步&am…

高性能架构—存储高性能

1 &#x1f4ca;关系型数据库 存储技术飞速发展&#xff0c;关系型数据的ACID特性以及强大的SQL查询让其成为各种业务系统的关键和核心存储系统。 很多场景下的高性能设计最核心的就是关系型数据库的设计&#xff0c;很多数据库厂商再优化和提升单个数据库服务器的性能方面做了…

Java Web应用升级故障案例解析

在一次Java Web应用程序的优化升级过程中&#xff0c;从Tomcat 7.0.109版本升级至8.5.93版本后&#xff0c;尽管在预发布环境中验证无误&#xff0c;但在灰度环境中却发现了一个令人困惑的问题&#xff1a;新日志记录神秘“失踪”。本文深入探讨了这一问题的排查与解决过程&…

激光切割机适用材质有哪些

激光切割机是一种利用激光束对各种材料进行高精度、高速度切割的机器设备。其适用材质广泛&#xff0c;包括但不限于以下两大类&#xff1a; 一、金属材料 不锈钢&#xff1a;激光切割机较容易切割不锈钢薄板&#xff0c;使用高功率YAG激光切割系统&#xff0c;切割不锈钢板的…

大厂面试真题-说一下Mybatis的缓存

首先看一下原理图 Mybatis提供了两种缓存机制&#xff1a;一级缓存&#xff08;L1 Cache&#xff09;和二级缓存&#xff08;L2 Cache&#xff09;&#xff0c;旨在提高数据库查询的性能&#xff0c;减少数据库的访问次数。注意查询的顺序是先二级缓存&#xff0c;再一级缓存。…

死锁的成因与解决方案

目录 死锁的概念与成因 栗子 死锁的情况 哲学家问题 如何避免死锁 必要条件 死锁的解决方案 总结 死锁的概念与成因 多个线程同时被阻塞,他们中的其中一个或者全部都在等待某个资源的释放,导致线程无限期被阻塞,程序无法停止 栗子 我和美女a出去吃饺子,吃饺子要醋和酱油…