图的存储-邻接矩阵&邻接表

图的存储

邻接矩阵

邻接矩阵适合存储稠密图。

在邻接矩阵 a a a 中,如果 a i , j a_{i,j} ai,j ∞ \infty ,代表 i i i j j j 之间没有边,否则 a i , j a_{i,j} ai,j 代表边 i → j i\rightarrow j ij 的权值。

Example

在邻接矩阵中这样存储:

∞ ∞ 2 ∞ ∞ ∞ ∞ ∞ ∞ 3 ∞ ∞ 2 ∞ ∞ 4 ∞ ∞ ∞ 3 ∞ ∞ 1 5 ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ \begin{array}{l} \infty & \infty & 2 & \infty & \infty & \infty \\ \infty & \infty & \infty & 3 & \infty & \infty \\ 2 & \infty & \infty & 4 & \infty & \infty \\ \infty & 3 & \infty & \infty & 1 & 5 \\ \infty & \infty & \infty & \infty & \infty & \infty \\ \infty & \infty & \infty & \infty & \infty & \infty \\ \end{array} 2323415

代码实现:

const int N = 1000;
int g[N][N]; // 邻接矩阵
// me -> 起点 | e -> 终点 | w -> 权值
// 把 me -> e 这条路的权值设为 w
void add(int me, int e, int v) { g[st][ed] = v; }

邻接表

邻接表用于在内存不够,无法使用邻接矩阵时存储图。

邻接表使用四个列表来存储图,hdnxt 实现链表存储每个点的出边,ed 存储每个边的终点,w 存储每个边的权值,用变量 idx 存储当前边的编号。

实现:

const int N = 10010, M = 100010;
int idx, hd[N], nxt[M], ed[M], w[M];
// N -> 点数 | M -> 边数
void add(int me, int e, int v) {
    ver[++idx] = e; // 设置终点
    w[idx] = v; // 设置权值
    nxt[idx] = hd[me]; // 实现链表
    hd[me] = idx;
}

Example

输入:

1 3 2
3 1 2
3 4 4
4 2 3
4 5 1
4 6 5
2 4 3

每次链表的状态:

hd: 1 0 0 0 0 0 | nxt: 0 0 0 0 0 0 0
hd: 1 0 2 0 0 0 | nxt: 0 0 0 0 0 0 0
hd: 1 0 3 0 0 0 | nxt: 0 0 2 0 0 0 0
hd: 1 0 3 4 0 0 | nxt: 0 0 2 0 0 0 0
hd: 1 0 3 5 0 0 | nxt: 0 0 2 0 4 0 0
hd: 1 0 3 6 0 0 | nxt: 0 0 2 0 4 5 0
------------------------------------
hd: 1 7 3 6 0 0 | nxt: 0 0 2 0 4 5 0

注:hdidx 中存储的都是边的编号。

寻找节点 4 4 4 的出边:

访问 hd[4] 6 6 6,代表有一条边 4 → e d 6 = 6 4\rightarrow ed_6=6 4ed6=6

访问 nxt[6] 5 5 5,代表有一条边 4 → e d 5 = 5 4\rightarrow ed_5=5 4ed5=5

访问 nxt[5] 4 4 4,代表有一条边 4 → e d 4 = 2 4\rightarrow ed_4=2 4ed4=2

访问 nxt[4] 0 0 0,代表没有其他出路。

代码如下:

int f; // 要寻找出路的节点
// 一直访问 nxt[i] 直到 i 为 0
for (int i = hd[f]; i; i = nxt[i])
    printf("%d %d\n", f, ed[i]);
    // 输出访问到的边的起点、终点编号。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值