数据结构--图


前言

本文主要是介绍图的一些基本概念、表示方法和应用场景;本文所涉及的知识点,主要是从网点:https://visualgo.net/zh学习记录所得。


一、相关概念

图按大类可分为简单图形和特殊图形。在简单图形中,节点没有从节点自身指向自身的边,且相邻节点之间也不存在多条边;而涉及其顶点或边有特定属性的图,一般都有特定的名称,如树,完整图,二分图,有向无环图,平面图,线图,星图,轮图等。
在这里插入图片描述

图也可以以边是否有方向,区分为有向图和无向图。如上图就是一个无向图, 无向图的一些基本概念如下:

  • 无向边e: (u,v)被认为是以其两个顶点入射:u和v。即无向边e的表示方法为,边(u, v),如边(0,2)
  • 相邻边缘,指两个边缘与公共顶点一起入射。如边(0,2)和边(2,4)就是相邻边缘。
  • 顶点的度数,是指与顶点v一起入射的边的数量,度为0的顶点被称为孤立顶点。例如,顶点0/2/6分别具有2/3/1的度数。
  • 子图,是指包含较小顶点和边的子集,如三角形{0,1,2}就是当前图的子图。
  • 路径,是指由一系列顶点组成,表示为 {v0, v1, …, vn-1, vn},且相邻顶点之间存在边e。如{0,1,2,4,5}就是一条路径。
  • 连通性,是指对于图中任何直接相邻的顶点,都存在边。如上图就是一个连通图。
  • 连通组件,需要满足三个条件,其1,图C是图G的子图;其2, 图C是连通的;其3,在图G中不存在包含图C的其它连通子图。如下图中,{0, 1, 2, 3, 4}和{5, 6}都是该图的连通组件。
    在这里插入图片描述

在有向图中,有些术语有所调整。
在这里插入图片描述

  • 有向边e,表示为(u->v),指v与u相邻,但反过来u与v就不一定相邻;如上图中,边(0->1)。
  • 顶点的度数区分为入度和出度,如顶点1的入度为2,出度为1;
  • 连通组件定义为强连通分量(SCC),如上图中,{0},{1,2 ,3}和{4,5,6,7}就是上图的三个SCC。
  • 循环,是指相同顶点开始和结束的路径。非循环的有向图称为,有向无环图(DAG)。

二、数据结构

有许多方法可以将图形信息存储到图形数据结构中。常见的有:邻接矩阵、邻接列表和边缘列表,每个都有自己优缺点和适用场景。

2.1 邻接矩阵(AM)

邻接矩阵AM是一个方形矩阵,大小为V*V(V为边的数量);其中AM[i][j]表示的是从顶点i到顶点j的权重值;对于无权重的图,可以认为其权重值为1;在c++语言中,常常以二维数组表示这个方形矩阵。
在这里插入图片描述
在这里插入图片描述

2.2 邻接列表(AL)

邻接列表(AL)是一个长度为V(V是顶点数量)的列表,AL[i]表示的是第i顶点的所有相邻顶点。对于权重图,可以把顶点编号和权重当成一个整体保存在AL[i]中。
在C++中,数据结构是:

  • 无权重图,vector<vector<int>> AL;
  • 权重图,vector<vector<pair<int,int>>> AL;

可以看出,无权重图的数据结构,也可以认为是vector<vector<pair<int,0>>> AL;
这样邻接矩阵就可以统一用一种数据结构表示。邻接列表空间开销是V(顶点数)+E(边数),是图最常用的表示方法。
在这里插入图片描述
在这里插入图片描述

2.3 边缘列表(EL)

边缘列表(EL),是具有连接顶点及其权重的边的集合。因此其空间开销为E(边的数量)。
在C++中,常见的数据表示方法为:
vector <tuple <int,int,int >> EL;
在这里插入图片描述
在这里插入图片描述
在上图中,共有7条边,因此列表的长度为7,在数据表示中,因为是无权重图,所以权重值并未体现出来,如顶点0,与顶点1和顶点2相连,可以看到EL[0]=(0,1) ,EL[1]=(0, 2)。

三、应用场景

把图的相应信息存储成对应的数据结构后,可以应用以下几个基本的场景。

  • 统计顶点数量
  • 统计边的数量
  • 统计某个顶点的所有相邻顶点
  • 判断边(u, v)是否存在等

3.1 统计顶点数量V

  • 对于邻接矩阵AM或者邻接列表AL,顶点数量V就是其行的长度;
  • 对于边缘列表EL,则不能这么直观的得出,一个最简单的方法,就是遍历EL,然后统计所有顶点,开销是O(E)。

此外,若在存储了图的信息后,不需要经常变更顶点和边缘,则在实际应用中,也可以用一个成员记录当前AM/AL/EL的数量,避免每次获取时都要重新计算。

3.2 统计边的数量E

  • 对于边缘列表EL,其边的数量是其长度。
  • 对于邻接列表AL,其边的数量等于每个顶点的相邻顶点数量的总和,且对于无向图来说,总数量需要除以2.
  • 对于邻接矩阵,可以遍历判断AM[i][j]的值,若值为0,即权重为0,则认为是顶点i和顶点j未连接;并且需要注意,AM[i][j]和AM[j][i]在无向图中,是表示同一条边的权重,不能重复计算。

3.3 枚举某一顶点u的所有邻居顶点

  • 对于AM,需要遍历AM[u][j], j 属于[0…v-1],找到AM[u][j]不为0的条件。开销是O(v)。
  • 对于AL,AL[u]的长度就是顶点u的邻居。
  • 对于EL,遍历的过程中,需要判断u出现的边。

3.4 检查边缘(u, v)是否存在

  • 对于AM,只需判断AM[u][v]是否不为0
  • 对于AL,只需判断AL[u]中,是否存在顶点v
  • 对于EL,若为无向图,则遍历并判断EL[i],其值是否是(u, v)或者(v, u);若是有向图,则只判断(u, v)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值