图的结构十分复杂,不仅各个结点的度不同,各个顶点之间的路径也不尽相同。但是图的主要组成部分比较清晰,分为顶点信息和边或者弧的信息。
邻接矩阵
邻接矩阵就是用一维数组存储图中顶点的信息,用一个二维数组表示图中各个顶点之间的邻接关系的信息,而这个二维数据就是邻接矩阵。
假设图有个确定的顶点,即,则表示中个顶点相邻关系为一个的矩阵,矩阵的元素为
其中,顶点与之间有边或者弧时为1,顶点与之间没有边或者弧时为0
如果是带权图,则有定义
其中,顶点与之间有边或者弧且权值为时为,对角线元素为0,顶点与之间没有边或者弧为。
无向图的邻接矩阵表示
邻接矩阵的特点
(1)无向图的邻接矩阵一定是一个对称矩阵。因此再存储邻接矩阵时只需存储上或者下的三角矩阵的元素即可。有向图的邻接矩阵不一定时对称矩阵。
(2)无向图的邻接矩阵的第行(或第列)非零元素(或非元素)的个数正好是第个顶点的度
(3)有向图的邻接矩阵的第行(或第列)非零元素(或非元素)的个数正好是第个顶点的出度(或入度)
(4)用邻接矩阵方法存储图,很容易确定图中任意两个顶点之间是否有边相连。要确定图中的边的个数,必须按行、列对每个元素进行检测。
(5)邻接矩阵存储稀疏图会浪费时间和空间。所以邻接矩阵适合存储稠密图。
邻接矩阵的存储算法
邻接矩阵的表示
由上面的定义得知在邻接矩阵的结构体中,不仅需要表示邻接矩阵的二维数组,还需要一个一维数组存储顶点信息。
const int M = 500;
typedef struct{
char ver[M]; //顶点表
int edg[M]; //边表,即邻接矩阵
int vernum,edgnum; //顶点数和边数
}MGraph;
邻接矩阵的创建
const int INF = 0x7f7f7f;
void CreatG(MGraph *G)
{
int ver1,ver2,w;
scanf("%d%d",&(G->vernum),&(G->edgnum)); //输入顶点数和边数
for(int i = 0;i<G->vernum;i++)
scanf("%c",&(G->ver[i])); //输入顶点信息,建立顶点表
/*创建无向图的邻接矩阵*/
memset(G->edg,0,sizeof (G->edg)); //初始化邻接矩阵
for(int i = 0;i<G->edgnum;i++)
{
scanf("%d%d",&ver1,&ver2); //输入边,建立邻接矩阵
G->edg[i][j] = 1; //无向图的邻接矩阵
}
/*创建带权图的邻接矩阵*/
for(int i = 0;i<G->edgnum;i++) //初始化邻接矩阵
for(int j = 0;j<G->edgnum;j++)
{
if(i == j)
G->edg[i][j] = 0;
else
G->edg[i][j] = INF;
}
for(int i = 0;i<G->edgnum;i++)
{
scanf("%d%d%d",&ver1,&ver2,&w); //输入边和权值,建立邻接矩阵
G->edg[i][j] = w; //有权值图的邻接矩阵
}
}