目录
介绍
图的建立一般有三种方式
一 邻接矩阵
二 邻接表
三 链式前向星
链式前向星是最节省空间的储存方法,只是代码稍微复杂一些
原理
建立静态数组edge和head
edge存储每条边的信息,如from,to,weight等边的信息,除此以外我们还要储存next。next表示的是edge下标中的例外一条边。
这两条边有什么联系吗,要用next存储?答案是两条边的from是相等的,如果我们以0作为终结flag,那么我们不断遍历next,直至遇0结束,就可以遍历一个节点的所有邻接节点
最原始的edge下标我们如何获取呢?这就是head数组的应用了,head[i]代表的是节点i的第一条边在edge中的下标信息,这相当于起始点的next信息。
数组的建立
首先开辟空间head[ N+5 ] 和edge[ M+5 ] ,N为节点数量,M为边数量
以0作为终结标志,那么egde和head初始化为0,意味着节点1-n的第一条边都不存在
接下来是添加边操作,创建函数addEdge(),传递的参数是需要的边信息,首先目的地是一定的,起始地在head中早已表明,可不添加,若有需要还可添加w权重等信息
在边的链表中我们只需每次向前插入即可,再修改head[i]起点边信息
void addEdge(int u,int v,int w){
edge[cnt].from=u;
edge[cnt].to=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt++;
return ;
}
代码
完整代码如下
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
const int M=2e6+5;
struct {
int from;
int to;
int next;
int w;
}edge[M];
int head[N];
int cnt=1;//点从1开始标记
void addEdge(int u,int v,int w){
edge[cnt].from=u;
edge[cnt].to=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt++;
return ;
}
int main(){
addEdge(1,2,2);
addEdge(1,4,4);
addEdge(2,1,1);
addEdge(2,5,5);
addEdge(2,4,4);
addEdge(4,1,1);
addEdge(4,5,5);
addEdge(5,2,2);
for(int i=0;i<6;i++)cout<<head[i]<<" ";cout<<endl;
for(int i=0;i<6;i++)cout<<edge[i].to<<" ";cout<<endl;
for(int i=0;i<6;i++)cout<<edge[i].next<<" ";cout<<endl;
return 0;
}
总结
链式前向星的原理其实就是静态数组模拟链表的思路,这样便可以实现有效利用空间储存边
当然,如果你创建了vector<int>edge[N+5]动态添加的话,那么前面的确实没有必要了。