邻接表

匿名 (未验证) 提交于 2019-12-02 23:56:01

数组实现邻接表

思路:

临接表是储存一条边的起点,终点,权重,用数组实现时用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]中储存。

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

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

将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; }

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