邻接表

試著忘記壹切 提交于 2019-11-28 23:08:30

数组实现邻接表

思路:

临接表是储存一条边的起点,终点,权重,用数组实现时用srtuct数组e中储存上述内容。

在储存时,我们储存起点的编号和终点的编号。

为了方便的遍历各点,我们还需要储存下一条边的位置。

 

emmmm非常抽象,我都不知道自己解释的啥玩意。

我们来用图片、代码和实例来说话(原谅我的画风)

int head[7], total, n, m;

struct edge {
    int u, v, w;
}e[10];

 

左边的条条是数组head,储存的是每个点第一个出边在数组e中的位置

右边的框框是数组e,每个格子储存3个元素,u起点,v终点,w权重

 

我们假设一共有6个点,9条边。

那我们一共就要储存6个点的第一条出边在e中的位置,即head[6+1]注意数组的结尾。

9条边分别储存在数组e中,即e[9+1]结尾同理。

 

解释完了变量我们开始输入

数据:

6 9      //点数和边数
1 2 1    //u v w w权重这里不多说,最后加上就行
1 3 12
2 3 9
2 4 3
3 5 5
4 3 4
4 5 13
4 6 15
5 6 4

1 2 1

点1连向点2权重为1

我们将head[1]赋值为1,表示点1的第一条出边储存在e[1]中。

那我们第一条边的起点有了,终点2呢?

我们将e[i]的元素u赋值为2,表示这条边的中点为2。

w为权重不解释。v马上解释,我们先讨论数组head。

这里的head可以看作是指针,指向点i的最后一条出边。

为什么是最后一条呢?刚才储存的明明是第一条。

先保留疑问,我们先储存第二条边。

 

1 3 12

点1连向点3 权重为12

根据刚才的操作,我们应该把head[1]赋值为2,表示1到3这条边储存在数组e[2]这个位置。

可是head[1]已经被占用了。

这时我们当然不能直接覆盖,我们可以先将head[1]的值保存在e[2]的v里。

 

那这个怎么理解?

刚才解释了head[1]=1表示点1的一条出边在e[1]中。

那我们将head[1]的值转移到e[2]的v中表示1到3这条边的下一条边在e[1]中储存。

可我们为什么要这么储存边?

因为我们在储存图时只关心点与点之间的联通关系,并不关心储存的顺序。

比如 1到2   1到3 和 1到3   1到2没有任何区别,只是顺序不同罢了。

将head中的数转移走了我们就可以储存新的起点了。

这样我们就储存了1>>>2 和1>>>3这两条边了。

指针的指向如下

因为1>>>2这条边是1的第一条出边,所以没有下一条出边,那v储存的便是0,表示没有下一条了,我这里是随便指向了end就表示没了。

 

然后让我们来储存剩下的点。

2 3 9

我们将这条边储存在e[3]中

head[2]=3;点2的第一条出边在e[3]中

然后将终点和下一条边的位置存在e[3]中

 

2 4 3

 

下面给出整张图的

 

代码实现

 

 

#include <iostream>
#include <cstdio>
#define N 1001

int head[N], total, n, m;

struct edge {
    int u, v, w;
}e[N];

void add(int u, int v) {
    total++;
    e[total].u = v;
    e[total].v = head[u];
    head[u] = total;
    return;
}

void test() {
    for (int i = 1; i <= m; i++)
    {
        printf("%d  >>>  ", i);
        for (int j = head[i]; j != 0; j = e[j].v)
            printf("%3d", e[j].u);
        printf("\n");
    }
    return;
}

int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= m; i++) {
        int a, b;
        scanf("%d%d", &a, &b);
        add(a, b);
    }
    test();
    return 0;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!