【图论基础·参考模板】用链式前向星表示图、图的DFS与BFS

一、图的表示方法 前向星与链式前向星

我们知道,一个图(Graph)是由若干顶点(Vertex,也称节点 / 结点(Node))和边(Edge)构成的。我们通过描述顶点与边的邻接关系来描述一个图。
边是图的基础元素。我们可以通过构建若干个边并令它们形成一定的关系来保存一个图。常用的表示方法包括指针、邻接矩阵和邻接表。
指针表示边的方法可参见我的博文 https://blog.csdn.net/COFACTOR/article/details/90733998 。这是一道关于二叉树的例题。树是一种特殊的、具有层次的图,因此表示树和图可以采用同样的方法。虽然用指针法表示二叉树不易出错,但是表示一些图则不一定(反正是队里的学长说的,我也不知道为啥)。
邻接矩阵是一种特殊的矩阵,如果顶点数为 v ,那么邻接矩阵就有 v 行 v 列。其每一项 a[i][j] 都只能取 0 或 1 。如果 a[i][j] = 1 ,表示顶点 i 到顶点 j 是连通的。这种表示方法既可以表示有向图也可以表示无向图。表示无向图的时候,邻接矩阵关于主对角线对称。
但是,如果图比较稀疏,由于二维数组占用的内存比较多,因此采用邻接矩阵表示一个图在多数时候都是不经济的。于是我们引入一个新的方法:邻接表。网上的大多数资料中也都用邻接表表示边。

(以下部分内容是根据博文 https://blog.csdn.net/acdreamers/article/details/16902023 改编的)
前向星属于邻接表的一种,我们通过构建一个边数组来储存前向星。前向星的构造方法是:把边数组 {<u, v>n} 中的每一条边先后按照起点 u 、终点 v 排序,并记录下以某个点为起点的所有边在数组中的起始位置和存储长度。

对于该图,我们输入:1 2 2 3 3 4 1 3 4 1 1 5 4 5
那么

不但需要由专门的数组记录边,还需要一个 head 数组来表示以某个顶点为起点的第一条边的存储位置。边的先后顺序是排序决定的。
为了尽量减少读入耗费的时间,一般采用无序排序的链式前向星来完成对图的记录。

首先定义边的结构体。结构体有两种,分别代表有向带权边和有向无权边:

struct Edge_w {
    unsigned NextStoPos = 0, to = 0, Weight = 0; };
struct Edge {
    unsigned NextStoPos = 0, to = 0; };

为了便于后续演示,我们先声明如下的全局变量:

Edge e[1000000]; unsigned head[1000], u, v;

e 是边数组,head 数组的意义同上。u、v 是顶点,输入用。
e[i].NextStoPos (很多资料中一般记作 next)表示同一顶点的下一条边在边数组 e[n] 中存储的位置(下标)。这个位置与输入的先后顺序有关。至于成员 to 则代表该边指向的顶点。
head[i] 代表以编号为 i 的顶点的第一条边在边数组 e[n] 中存储的位置(下标),也与输入顺序有关。
顶点应该从 0 或 1 开始依次按顺序编号。如果从一个比较大的数开始编号,而且中间总是跳过一些数,进而导致某些顶点的编号巨大,就可能会导致 head 数组的下标越界。但好在许多题目一般都是从 0 或 1 开始对顶点依次编号的。

定义边的结构体以后,为了能保存每条边,还需要编写添加边的函数:

inline void AddEdge(unsigned* RevIdx, Edge_w* Edge, const unsigned& vtx_u, const unsigned
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值