这方面的基础是很差,所以总结一下。
存图的常用方式有三种:邻接矩阵法,邻接表,链式前向星。
下面一 一介绍:
邻接矩阵法
用一个二维矩阵来存储一张图,矩阵中的i行j列代表 顶点i到j是否存在边,存在的话该值即为该条路径权值。
当该图为无向图时,主对角线上下是对称的。
这种存储方式非常容易理解,且可在O(1)时间内实现删除,修改,添加操作。但是它仅适用于顶点不是很多的情况,当顶点数很大的情况下会需要非常大的内存空间。
同时,它适用于稠密图的存储,这样可以很好的利用内存空间。
int map[maxn][maxn];
int main(
{
scanf("%d %d %d",&start,&end,&weigh);
map[start][end]=weigh//当它为无向图时 还需设置map[end][start]=weigh;
return 0;
}
邻接表存储法
链式的存储方法,顶点链式相连(顶点表),每一个顶点又连接着一条链,即以该顶点为起始点的边(边表)。
由于链式实现比较复杂,实际做题容易出错,所以这里采用数组来模拟链表。
相比邻接矩阵,邻接表节省了内存空间,适合稀疏图的存储。
它的复杂度是O(n+m)
而遍历一次图的时间复杂度也是O(n+m) 效率高于邻接矩阵法
int cnt,cost[maxn],from[maxn],to[maxn],Next[maxn], head[maxn];
int n,m;//m条边,n个顶点 ,下面假设已经得到了它们的值。
void add(int x,int y,int z)//添加该边
{
++cnt;
cost[cnt]=z;
from[cnt]=x;
to[cnt]=y;
Next[cnt]=head[x]; //next存储的是上一条边的号
head[x]=cnt;//head[x]在这里存的是以x为起点的第一条边,不断更新
}
int main()
{
cnt=1;
for(int i=1;i<=m;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);//起点、终点、权重
add(x,y,z);add(y,x,0); //刚开始要建反向边,容量是0
}
}
链式前向星
链式前向星实际上就是邻接表的另一种实现形式,这里采用的是结构体的形式,比起全用数组模拟更加方便。
int head[maxn], cnt=0;//head数组用来表示以i为起点的一条边存储的位置
struct Edge
{
int next; //同一起点的上一条边的储存位置
int to; //此边的终点
int w; //此边的权重
}edge[maxn];
void add(int u,int v,int w) //初始化加边
{
edge[cnt].w = w;//记录边的权重
edge[cnt].to = v;//记录边的终点
edge[cnt].next = head[u];//存储同一起点的上一条边的位置
head[u] = cnt++;//给边赋予序号
}
int main()
{
for(int i=0; i<=n; i++)
for(int j=head[i]; j!=-1; j=edge[j].next) //链式前向星的遍历方法
}
后两种方法相对来说难理解一点,初学可以自己模拟几次建图的流程。
https://blog.csdn.net/qq_41754350/article/details/81082728
链式前向星我是看了这位博主的模拟流程才弄明白。