链式前向星

对于初学者来说前向星是不太好理解的,想当初蒟蒻的我就是怎么看都不明白,一直钟爱于邻接矩阵和邻接表

but 作为一种特别的储存数据的结构,前向星有着其妙妙的作用,所以还是硬着头皮学吧

我们首先来看一下什么是前向星.

前向星是一种特殊的边集数组,我们把边集数组中的每一条边按照起点从小到大排序,如果起点相同就按照终点从小到大排序,

并记录下以某个点为起点的所有边在数组中的起始位置和存储长度,那么前向星就构造好了.

用len[i]来记录所有以i为起点的边在数组中的存储长度.

用head[i]记录以i为边集在数组中的第一个存储位置.

那么对于下图:

我们输入边的顺序为:

1 2

2 3

3 4

1 3

4 1

1 5

4 5

那么排完序后就得到:

编号:     1      2      3      4      5      6      7

起点u:    1      1      1      2      3      4      4

终点v:    2      3      5      3      4      1      5

得到:

head[1] = 1    len[1] = 3

head[2] = 4    len[2] = 1

head[3] = 5    len[3] = 1

head[4] = 6    len[4] = 2

但是利用前向星会有排序操作,如果用快排时间至少为O(nlog(n)

如果用链式前向星,就可以避免排序.

我们建立边结构体为:

1 struct Edge
2 {
3      int next;
4      int to;
5      int w;
6 };

其中edge[i].to表示第i条边的终点,edge[i].next表示与第i条边同起点的上

另外还有一个数组head[],它是用来表示以i为起点的第一条边存储的位置,实际上你会发现这里的第一条边存储的位置其实

在以i为起点的所有边的最后输入的那个编号.

head[]数组一般初始化为-1,对于加边的add函数是这样的:

 1 #include<cstdio>
 2 using namespace std;
 3 struct sd{
 4   int to,w,next;  
 5 }edge[10005];
 6 int head[10005];//要先赋初值=-1;
 7 int num=0;
 8 void add(int a,int b,int w)
 9 {
10     num++;
11     edge[num].to=b;
12     edge[num].w=w;
13     edge[num].next=head[a];
14     head[a]=num;
15 }

这样就可以基本实现图的加边操作。
当然这个方法肯定不如链表,邻接矩阵好理解,但在许多图论与网络流题目中很实用。

原文地址:https://www.cnblogs.com/genius777/p/8470111.html