对于图的储存结构,最常用有两种方式:

  1. 邻接矩阵的存储
  2. 邻接链表的存储

今天我们就来介绍一下关于图结构中,邻接矩阵到底是什么,到底该如何存储,示例代码又是怎样等问题。

我们从最简单的说起,如果给你下面一张图,怎么样才能把这张图给存储到计算机中呢?

python邻接矩阵可视化_数据结构

从图中我们可以看到,对这样一个图结构来说,最引人注目的不就是图中的顶点了,就是这两个元素构成了一个图,图也表示了两个或者多个顶点之间是否有关系。介绍完了图“长”这样以后,我们来讨论下图的种类;图分为有向图和无向图两种,顾名思义,就是表示图中的边是否有方向。

python邻接矩阵可视化_python邻接矩阵可视化_02

接下来我们说说如何用邻接矩阵把这两种图存储起来(实际上代码上只有小小的区别,只是两种理解不一样)。

首先对于无向图来说,我们首先要让计算机知道我们想要存储的图有几个顶点,有几条边,这很重要,所以我们在程序的开始就需要n(顶点)和e(边数),我们直接看下图这个例子:

python邻接矩阵可视化_图的存储结构_03

对于后面这个图,仔细想想的确能够表示前面这个图,1表示存在边,0表示不存在边;看矩阵,比如(1,1),表示1顶点和1顶点没有关系(在数据结构中,我们认为顶点自己的自环不算存在关系,当然在离散数学中是可以的),再比如(1,2)表示1和2顶点有关系,比如(3,4),表示3,4两个顶点有边。比如有4个顶点,那就生成4x4的矩阵。

其实细心的同学已经发现有个特点:

python邻接矩阵可视化_python邻接矩阵可视化_04

那就是这个矩阵是个对称矩阵,因为这是一个无向图,1和2有边,2和1也一定有边吧,就好像两个人是好朋友一样,互相有关系。

接着我们说说有向图,其实理解了无向图,其实有向图也就很容易了,不就是多个方向嘛。

python邻接矩阵可视化_图的存储结构_05

此时我们就要注意了对于有向图中,矩阵样子是和无向图差不多的,但是理解不一样;比如(1,2),在无向图中表示顶点1和顶点2有关系,而<1,2>在有向图指顶点1指向顶点2有一条边,这里要分清楚集合和序偶的概念。所以,自然有向图的矩阵就不一定对称了。

我以第一个无向图为例子,运行代码:

python邻接矩阵可视化_权值_06

接下来说说关于权值的问题,什么是权值,也就是说这条边的的“权力大小”,也就是这条边的特殊性,把之前的有向图加上权值就是这样:

python邻接矩阵可视化_图的存储结构_07

也就是给每个边加上权值,在以后图的遍历中,权值的大小也会决定图遍历的路径。但是对于邻接矩阵来说,无非就是把之前的“1”改为对应的权值就行了,很简单。

python邻接矩阵可视化_权值_08

接下来的代码示例,指的是(有向图+权值)的例子,要改为无向图或者取消权值,稍加修改就可以,我已经注释在代码中了。

# include <stdio.h>
# include <stdlib.h>
# define MAX 20
typedef int VexType;
typedef  VexType Mgraph[MAX][MAX];   //二维矩阵 
void creat_mg(Mgraph G);
void out_mg(Mgraph G);
Mgraph G1;                         
int n,e;

main()                              //主函数 
 { creat_mg(G1);     out_mg(G1);
 }

void creat_mg(Mgraph G)            //创建邻接矩阵 
{ int i,j,k,w;
  printf("\n  输入顶点数n和边数e (空格分开)=?"); scanf("%d%d", &n,&e); 
  for(i=1; i<=n;i++)
       for(j=1;j<=n;j++) G[i][j]=0;  //这里是矩阵的初始化     
                    
  for(k=1;k<=e;k++)                                
     { printf("\n  vi,vj,权值w(空格分开)=?"); 
       scanf("%d%d%d", &i,&j,&w);    //如果不需要权值,就不用输入w     
	   G[i][j]=w;  //如果是无向图这里就为“G[i][j]=1,G[j][1]=1;” 
				   //相当于对称矩阵,对角线复制一下就行了 
     }
 } 
 
void out_mg(Mgraph G)              //打印邻接矩阵 
 { int i,j,k;  char ch;
   printf("邻接矩阵为:\n");
   for(i=1; i<=n;i++)       
     { printf("\n ");
       for(j=1;j<=n;j++) printf("%5d",G[i][j]);
     }
   for(i=1; i<=n;i++)
      for(j=1;j<=n;j++)
         if(G[i][j]!=0)printf("\n 存在边< %d,%d >",i,j);
     printf("\n\n   打回车键,继续。");getchar();
 }

其实对于图来说,邻接矩阵的存储是不难的,拿出笔来,自己在纸上画一画图,相信很容易就能理解的