静态链表(链式前向星)是表示图的另外一种方法

前向星

前向星也称为邻接数组

总共有这几条边

(1, 2)
(2, 4)
(3, 4)
(1, 3)
(4, 3)
(3, 2)
(1, 4)

现在将这些边按从小到大排序,变成
(1, 2) --|
(1, 3) --| => len[1] = 3
(1, 4) --|
(2, 4)
(3, 2) => head[3] = 5
(3, 4)
(4, 3)

然后再将数据填入三个数组中,分别是
es[] 这个数组是用来记录每条边的终点的,而因为前面已经排好了序,起点很容易知道
head[] 记录以i为起点的边在数组中的第一个位置
len[] 记录以i为起点的边有多少

Array 1 2 3 4 5 6 7
es 2 3 4 4 2 4 3
head 1 4 5 7
len 3 1 2 1

head[2]=4表示2为起点的第一条边在es中的位置为4

通过这几个函数我们就能很清楚的知道点与边的关系

例如,我们想知道起点为1的所有边,我们只需要知道len[1]和head[1],这样我们知道起点为1的边有三个且从es[1]开始

但是前向星要排序,时间复杂度高,因此并不怎么使用

邻接表

邻接表通常用vector来实现

vector g[max_v],g[i]表示了以i为起点的所有边

链式前向星

其他部分与前向星相同,但是链式前向星多了一个next数组,取消了len数组(因为没有排序了)

next数组的含义是下一条以i为节点的边在es中的位置,如果这是最后一个节点,则令next[i]=0

例如

Array 1 2 3 4 5 6 7
es 2 4 4 3 3 2 4
head 1 2 3 5
next 4 0 6 7 0 0 0

举个例子,我们要求以1为起始边的所有节点

先从head中知道了第一个以1为起始点的边是1号,所以可以知道(1,2),然后next[1]=4,而4的es=3,所以(1,3)也知道,然后同理


const int maxn=100+10;
const int maxm=1000+10;
int head[maxn];
int n,m,nEdge; //n为顶点数,m为边数,nEdge为存储的边的数量
//如果边是双向的,那么存储的边的数量就是2m
struct NODE//这里是双向的
{
int to;
int next;
};
NODE edge[maxm<<1];
void addedges(int u,int v) //将边(u,v)添加进去
{
nEdge++;
edge[nEdge].next=head[u];
edge[nEdge].to=v;
head[u]=nEdge;
}
void foreach() //遍历边
{
int i,k;
for(i=1;i<=n;i++)
{
for(k=head[i];k!=-1;k=edge[k].next)
{
cout<<i<<" "<<edge[k].to<<endl;
}
}
}
void Init()
{
nEdge=-1;
memset(head,0xff,sizeof(head));
int u,v;
for(int i=0;i<m;++i)
{
cin>>u>>v;
addedges(u,v);
addedges(v,u);
}
}