链式前向星
链式前向星
我写图论题的时候喜欢用vector,因为直观,方便操作和初始化。后来遇到了有些图论的题,发现很多时候用vector会超时,邻接表又写起来麻烦,看了很多大佬的解题报告都用的链式前向星存储结构。这几天看了各大大佬的博客之后,我对链式前向星有了自己的理解与运用,由于大佬的博客都有版权声明,不方便转载,所以我自己来重新写一篇。
先谈谈个人的理解吧,链式前向星是通过对边的下标进行操作来实现邻接表的功能的一种存储结构。
首先,前向星包括一个结构体Edge
typedef struct Edge
{
int to; //用来存储第i条边的另一个节点
int val; //用来存储权
int next; //用来存下同一起点的下一条边的下标(与边的输入顺序是相反的方向)
} Edge;
还有一个head数组,head数组用来存以i为起点的最后一条边的另一个节点,其初始化为-1。
介绍完主要成员后,接下来就是add函数,add函数的作用是实现边的存储。写法如下。
void add(int u,int v,int val)
{
edge[cnt].to=v;
edge[cnt].val=val;
edge[cnt].next=head[u];
head[u]=cnt++;
}
//这里的cnt最开始初始化为0,表示边数
接下来就是遍历方法。假如我现在想遍历所有u可以到达的节点。
for(int i=head[u]; i!=-1; i=edge[i].next) //很多大佬都把i!=-1写成~i
{
int cur=edge[i].to; //这里的cur变量就是u到达的节点
int value=edge[i].val; //value存储的是u->cur的权
...
}
上面已经讲到,head数组用来存以i为起点的最后一条边的另一个节点,next是记录下一条边的下标的。举个栗子,现在我要存下面一组数据
//分别对应u v w(有向图)
1 2 10
2 4 5
2 1 60
1 3 20
3 4 10
4 1 50
那么表示成表的形式是(简陋一点)
起点 终点
1 2、3
2 4、1 //这里的顺序是按照边的输入顺序,并非节点大小
3 4
4 1
模拟出每个步骤就是
edges[1].to=2 edge[0].next=-1 head[1]=0
edges[2].to=4 edge[1].next=-1 head[2]=1
edges[2].to=1 edge[2].next=1 head[2]=2 //更新节点2对应的最后一个节点,这里是edges[2].to就是节点4
edges[1].to=3 edge[3].next=0 head[1]=3 //与上面类似
edges[3].to=4 edge[4].next=-1 head[3]=4
edges[4].to=1 edge[5].next=-1 head[4]=5
最后结果就是
edges[0].to=2 edges[0].next=-1 head[0]=-1
edges[1].to=4 edges[1].next=-1 head[1]=3
edges[2].to=1 edges[2].next=1 head[2]=2
edges[3].to=3 edges[3].next=0 head[3]=4
edges[4].to=4 edges[4].next=-1 head[4]=5
edges[5].to=1 edges[5].next=-1 head[5]=-1