图(有向图和无向图)的储存方法有邻接矩阵和邻接表两种储存方式。其中邻接表有两种实现方式:1.指针。2.数组
后者使用比较方便简洁,这里介绍一下用数组实现邻接表储存图
输入数据
4 5
1 4 9
4 3 8
1 2 5
2 4 6
1 3 7
4表示顶点个数 5表示输入的边数
用邻接表储存这个图,代码如下
#include<stdio.h>
int main(void)
{
int n,m;//n表示顶点个数,m表示输入的边数; 这里用n=4(点),m=5(边);举例
int i,k;
int u[6],v[6],w[6];//第一,二个数组是储存顶点的,第三个是储存该边的权值的;
//这三个数组的大小要根据m来定,比m大一就行了;
int first[5],next[6];
//这两个数组也要看实际,first数组比n(顶点)大一,next数组比m(边)大一
scanf("%d %d",&n,&m);
for(i=1;i<=n;i++)
first[i]=-1;//初始化first数组,表示1~n顶点暂时还没有连接的边;
for(i=1;i<=m;i++)
{
scanf("%d %d %d",&u[i],&v[i],&w[i]);//依次输入顶点和所连接的边权值
//下面两句是关键
next[i]=first[u[i]];
first[u[i]]=i;//为边编号,保证遍历时u[],v[],w[]输出的准确
}
printf("\n");
/*其实就是 最终储存依次 从一个顶点出发的所有边(i其实就是这些边的编号)
下面是邻接表的遍历输*/
for(i=1;i<=n;i++)
{
k=first[i];/*选出顶点 1 开始遍历 first可以理解为储存顶点编号,
其实 也储存了最后一次输入边的编号*/
while(k!=-1)//一直输出与该点连接的边直到没有(next【】==-1)
{
printf("%d %d %d\n",u[k],v[k],w[k]);//其实k就是边的编号
k=next[k]; //变为该顶点连接的下一条边 的编号
}
}
return 0;
}
输入输出如下
first[5]= {5,4,-1,2}这里的值都是最后一次输入边的编号
next[6]={-1,-1,1,-1,3}
可以发现使用邻接表来储存图的时间空间复杂度是O(M),遍历每一条边的时间复杂度也是O(M)。如果是稀疏图的话,M要远小于N^2
我们可以使用邻接表来代替邻接矩阵降低时间复杂度,邻接表最坏的情况下才和邻接矩阵一样,但是一般情况下并不会有那么多边。