对于初学者来说前向星是不太好理解的,想当初蒟蒻的我就是怎么看都不明白,一直钟爱于邻接矩阵和邻接表
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 }
这样就可以基本实现图的加边操作。
当然这个方法肯定不如链表,邻接矩阵好理解,但在许多图论与网络流题目中很实用。