图的存储方式
posted on 2023-01-16 13:22:29 | under 笔记 | source
本文主要介绍图的几种存储方式。

先掏出一张图,设上图有 n 个点、m 条边。
那么怎么存储它呢?下面介绍三种常用方式。
- 邻接矩阵
- 二维 vector
- 链式前向星
邻接矩阵
构建 a 数组,其中 $ a[i][j]$ 表示是否能从点 i 到点 j 。
如:$ a[1][2]=1 $ 。
代码:
int n,m,x,y;
int a[1005][1005];
cin>>n>>m;
for(int i=1; i<=m;i++)
{
cin>>x>>y;
a[x][y]=1;
//需要注意的是,对于无向图还需反向建边一次
}
空间复杂度 $ n^2 $ 。
二维 vector
可以理解为邻接矩阵的优化版,用到了动态数组。
有两维,第一维代表点,第二维代表该点连接的点。
代码:
int n,m,x,y;
vector<int>v[1005];
cin>>n>>m;
for(int i=1; i<=m;i++)
{
cin>>x>>y;
v[x].push_back(y);
}
for(int i=1; i<=n;i++)
for(int j=0; j<v[i].size();j++)
{
cout<<i<<"->"<<v[i][j]<<endl;
}
空间复杂度 $ nm$ 。
链式前向星
需要定义结构体 edge 数组。
每个元素包含:下一个与该边同起点的边序号、终点、边权等。
struct e
{
int next; //下一条边
int w; //边权
int v; //终点
}edge[100005];
我们再引入一个数组 head ,表示以 u 为起点所指向的一条边。
这样就可以完成加边操作了。
void add(int u,int v,int w)
{
//cnt代表当前有几条边
edge[++cnt].w=w;
edge[cnt].v=v;
edge[cnt].next=head[u]; //将下一条边指向头
head[u]=cnt; //将头设为这条边
}
最后是遍历,由一点延伸出的边:
for(int i=head[u]; i;i=edge[i].next)
{
cout<<u<<"->"<<edge[i].v<<endl;
}
空间复杂度 $ m$。
总结
几种方式都有各自优劣,邻接矩阵在稠密图中效率高,链式前向星在稀疏图中占优。
最后,这几种方法都是很重要的基础,要多熟悉熟悉它们。

浙公网安备 33010602011771号