C++ 图(三十六)【第二篇】

上期说到...:

VCR·:

图片

那我们接着说,话说我们讲了这么多,我们该如何储存图呢???

有两种:

  1. 邻接矩阵

  2. 邻接表

那我们就学习一下吧!

1.邻接矩阵的创建与访问插入

1.标记回顾

在之前的课程中,我们学过数组下标的更多应用,例如我们可以使用数组标记某个数是否出现过。

具体实现为:

C++ 图(三十六)【第二篇】_第1张图片


我们回到图中,在图中我们可以明确的知道某个顶点 
u 向其他顶点 v 的连接情况。那么对于顶点 
u 我们可以使用一维数组 vis[ ]标记它可以向哪些顶点连边。如果存在 u→v 的边,我们使用 vis[v]=1 进行标记,反为 vis[v]=0。

下面是顶

点 
1 的 vis[ ]:

C++ 图(三十六)【第二篇】_第2张图片

2.正文

在这一节我们来学习图的一种储存方式——邻接矩阵。

什么是邻接矩阵呢?所谓邻接矩阵存储结构就每个顶点用一个一维数组存储边的信息,这样所有点合起来就是用矩阵表示图中各顶点之间的邻接关系。所谓矩阵其实就是二维数组。

对于有 n 个顶点的图 G=(V,E) 来说,我们可以用一个 n×n 的矩阵 A 来表示 G 中各顶点的相邻关系,如果 v[i] 和 
v[j] 之间存在边(或弧),则 A[i][j]=1,否则 A[i][j]=0。

下图为有向图对应的邻接矩阵:

C++ 图(三十六)【第二篇】_第3张图片

下图为无向图对应的邻接矩阵:

C++ 图(三十六)【第二篇】_第4张图片

3.邻接矩阵的使用

一个图的邻接矩阵是唯一的,矩阵的大小只与顶点个数 
N 有关,是一个 N×N 的矩阵。前面我们已经介绍过,在无向图里,如果顶点 v[i] 和 v[j] 之间有边,则可认为顶点 v[i] 到 
v[j] 有边,顶点 v[j] 到 
v[i]也有边。对应到邻接矩阵里,则有 A[i][j]=A[j][i]=1。因此我们可以发现,无向图的邻接矩阵是一个对称矩阵。

在邻接矩阵上,我们可以直观地看出两个顶点之间是否有边(或弧),并且很容易求出每个顶点的度,入度和出度。

这里我们以下图为例,演示下如何利用邻接矩阵计算顶点的入度和出度。顶点的出度,即为邻接矩阵上点对应行上所有值的总和,比如顶点 11 出度即为 

0+1+1+1=3;而每个点的入度即为点对应列上所有值的总和,比如顶点 
3 对应的入度即为 1+0+0+1=2。

C++ 图(三十六)【第二篇】_第5张图片

接下来我们就先一起学习构造和使用邻接矩阵的方法。邻接矩阵是一个由 

1 和 0 构成的矩阵。处于第 i 行、第 
j 列上的元素 1 和 
0 分别代表顶点 i 到 
j 之间存在或不存在一条有向边。

显然在构造邻接矩阵的时候,我们需要实现一个整型的二维数组。由于当前的图还是空的,因此我们还要把这个二维数组中的每个元素都初始化为 0。

4.初始化

在构造好了一个图的结构后,我们需要把图中各边的情况对应在邻接矩阵上。实际上,这一步的实现非常简单,当从顶点 

�x 到 �y 上存在边时,我们只要把二维数组对应的位置置为 11 就好了。

C++ 图(三十六)【第二篇】_第6张图片

用邻接矩阵来构建图需要如下几步,我们可以用二维数组G[][]来表示一个图。

初始化

初始化的过程很简单,只需要把数组初始化为 
0 即可。可以借助memset来快速地将一个数组中的所有元素都初始化为 0。

图片

注意,memset只能用来初始化 0,
−1,并且需要加上头文件cstring。

上面的代码等价于:

C++ 图(三十六)【第二篇】_第7张图片


当然我们平常使用邻接矩阵的时候下标只用 1 到 
n 或者 00 到 n−1 (这个看题目中点的编号)。

5.插入与访问边
  • 如果插入一条有向边 
    (u,v),只需要G[u][v] = 1;。

  • 如果插入一条无向边 
    (u,v),只需要

     

    也可以写成G[u][v] = G[v][u] = 1;。

  • 图片

如果G[u][v] = 1,说明有一条从 
u 到 v 的边,否则没有从 u 到 v 的边。

你可能感兴趣的:(算法)