图的存储方式

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$。

总结

几种方式都有各自优劣,邻接矩阵在稠密图中效率高,链式前向星在稀疏图中占优。

最后,这几种方法都是很重要的基础,要多熟悉熟悉它们。

posted @ 2026-01-15 08:21  Zwi  阅读(3)  评论(0)    收藏  举报