图的存储——前向星与链式前向星

图的存储与围绕某一结点的遍历

稀疏矩阵怎么存储?图太大了不能用二维数组的邻接表怎么办?该如何遍历与某一结点相连的所有边?

我们将围绕这个图进行展开。
在这里插入图片描述

设该图的输入如下:

/*
1 2
2 3
3 4
1 3
4 1
1 5
4 5
*/

前向星

前向星是一种特殊的边集数组,我们把数组中的每一条边按照起点从小到大排序,如果起点相同,则按照终点从小到大排序,并记录下以某个点为起点的所有边中第一条边的位置以及所有边的数量。

len[i]:以i为起点的所有边的数量。

head[i]:数组经过排序后,以i为起点的所有边中第一条边在数组中的下标。

如上图, 对边集排序后我们可以得到:

// 数组下标: 1 2 3 4 5 6 7 (方便起见,我们从1开始)
// 起    点:1 1 1 2 3 4 4
// 终    点:2 3 5 3 4 1 5

那么其对应的len数组和head数组即为:

//       1 2 3 4 5
// head: 1 4 5 6 (INF/0) (不存在时可以设置一个不会在图中出现的值)
// len : 3 1 1 2 0

这样我们就得到了前向星。

链式前向星

在使用前向星的时候,我们需要排序,而链式前向星则不需要。在实际使用过程中链式前向星也更为广泛。

首先我们建立结构体:

// e[i]表示输入的第i条边
struct Edge{
    int next; // 记录与e[i]同起点的下一条边的数组下标
    int to;   // 记录e[i]的终点
    int w;    // 记录第i条边的权重值
}e[N];

这样我们得到了所有边的信息。

但是当我们需要遍历某个结点的所有边时,仅仅有这些还不够,我们还需要一个关键性的数组:head

head数组用来记录以i为起点的最后一条边在e数组中的数组下标。一般初始化为-1

这样我们需要的东西就齐全了。接下来是存储:

int cnt = 0;
void add(int u, int v, int w) {
    e[cnt].w = w;
    e[cnt].to = v;
    e[cnt].next = head[u];
    head[u] = cnt++;
}

我们按照上图进行模拟,得到如下结果:

e下标tonexthead下标head
02-110
13-121
24-132
33013
41-144
55315
65446

通过表可以看出,head存储的是最后一条边,这样的话遍历的时候就是倒着遍历的,不过并不影响结果的正确性。

遍历结点u的操作就是这样的:

for (int i = head[u]; ~i; i = e[i].next)

觉得不错的话记得点个赞呀~~


参考资料

https://blog.csdn.net/acdreamers/article/details/16902023

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值