图的存储结构

1 邻接矩阵

1.1 定义

int G[N][N] 如果没有特殊指定, 下文的 n n n表示点数, e e e表示边数
g [ i ] [ j ] g[i][j] g[i][j]表示点 i i i j j j边的权值
i i i j j j之间连边时, g [ i ] [ j ] = 1 g[i][j] = 1 g[i][j]=1或权值
i i i j j j之间不连边时, g [ i ] [ j ] = 0 g[i][j] = 0 g[i][j]=0 ∞ \infty
例: 在这里插入图片描述
这个图的邻接矩阵:
G = [ ∞ 2 5 4 ∞ ∞ 2 1 ∞ ∞ ∞ 3 ∞ ∞ ∞ ∞ ] G = \left[ \begin{matrix} \infty & 2 & 5 & 4 \\ \infty & \infty & 2 & 1 \\ \infty & \infty & \infty & 3 \\ \infty & \infty & \infty & \infty \end{matrix} \right] G= 252413

1.2 参考代码

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n, e;
int g[105][105];
int main(){
	// 初始化为很大的数, 不带权的图第二个空填0
	memset(g, 0x3f, sizeof(g));
	scanf("%d %d", &n, &e);
	int a, b, c;
	for(int i = 1;i <= e;i++){
		scanf("%d %d %d", &a, &b, &c);
		g[a][b] = c;  // 不带权的图: g[a][b] = 1
		g[b][a] = c;  // 无向图的对称性, 有向图不要这一句
	}
	return 0;
}

2 链式前向星

邻接矩阵的空间复杂度为 O ( n 2 ) O(n^2) O(n2), 数据量大的时候会爆内存

2.1 定义

邻接表由 3 3 3个数组模拟, 有权值还要多加一个数组, 以下为数组表示的内容:
h e a d [ N ] head[N] head[N]: 这个点连接的第一条边, h e a d [ i ] = − 1 head[i] = -1 head[i]=1表示 i i i没有连边
t o [ E ] to[E] to[E]: 这条边到达的点
n e [ E ] ne[E] ne[E]: 即 n e x t next next, 这条边起点连接的下一条边, n e [ i ] = − 1 ne[i] = -1 ne[i]=1表示, 这已经是边 i i i起点的最后一条连边
w [ E ] w[E] w[E]: 这条边的权值, 只在有权值的图中

2.2 加边

在这里插入图片描述这个图的邻接表:

数组名 \ 下标123456
head356-1
to234344
ne-112-14-1
w254213

2.3 输出

可以看到, 每一个点 i i i连接的第一条边是 j = h e a d i j = head_i j=headi, 到达的点和边权存在 t o j , w j to_j, w_j toj,wj里, 而 i i i的下一条边就是 j = n e j j=ne_j j=nej, 直到 j = − 1 j = -1 j=1结束

2.4 参考代码

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n, e;
int head[105], to[105], ne[105], w[105], idx = 1;
void add(int a, int b, int c){
	to[idx] = b;
	w[idx] = c;
	ne[idx] = head[a];
	head[a] = idx++;
}
int main(){
	memset(head, -1, sizeof(head));  // 初始化
	scanf("%d %d", &n, &e);
	int a, b, c;
	for(int i = 1;i <= e;i++){
		scanf("%d %d %d", &a, &b, &c);
		add(a, b, c);  // 不带权的图: add(a, b)
		add(b, a, c);  // 无向图的对称性, 有向图不要这一句
	}
	for(int i = 1;i <= n;i++){
		printf("%d: ", i);
		for(int j = head[i];j != -1;j = ne[j]){
			printf("%d(%d)", to[j], w[j]);
		}
	}
	return 0;
}

3 邻接表

对于链式前向星有时一个点连接的边太多, 例如在稠密图中大量判断哪些点是否相连, 有可能TLE

3.1 定义和使用

邻接表是由一个二维 v e c t o r vector vector数组构成的, v e c t o r vector vector的优点是可以动态修改大小
g [ i ] [ j ] g[i][j] g[i][j]表示第 i i i个点第 j j j条边连接的点, 如果有权值
加边: g[a].push_back({b, c})
访问: 外层遍历点 i i i, 内层遍历 j : 0 ∼ g [ i ] . s i z e ( ) − 1 j: 0 \sim g[i].size()-1 j:0g[i].size()1, g [ i ] [ j ] g[i][j] g[i][j]就是连接的点

3.2 参考代码

#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
int n, e;
vector<pair<int, int>> g[105];
int main(){
	g.clear();
	scanf("%d %d", &n, &e);
	int a, b, c;
	for(int i = 1;i <= e;i++){
		scanf("%d %d %d", &a, &b, &c);
		g[a].push_back({b, c});  // 不带权的图: add(a, b)
		g[b].push_back({a, c});  // 无向图的对称性, 有向图不要这一句
	}
	for(int i = 1;i <= n;i++){
		printf("%d: ", i);
		for(int j = 0;j < g[i].size();j++){
			printf("%d(%d)", g[i][j].first, g[i][j].second);
		}
	}
	return 0;
}

4 总结

存储结构数据结构空间复杂度单次访问时间
邻接矩阵二维数组O(n2)O(1)
邻接表4个一维数组O(n)平均每个点连边数量
前向星二维vectorO(n+e)vector下标访问速度

Y1.8 Nov.11.2023 Sat.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值