对于存储图的信息有很多种方式,比如邻接二维矩阵或者是直接用几个数组存储。但这些方法对于数据过多的情况会卡壳,毕竟要开辟一个比较大的空间,而且空间的利用效率不高。
或许有些题目给我们的要求是找到某一个顶点所在的边,这样的题目看上去不难,循环存入数据后,再循环查找便可以实现了。但是还有更简单的方法,可以在存入数据的同时找到某一个顶点所在的边。
就是接下来要讲的——链式前向星。
特性
1、内存的利用率高,节省时间、空间。
2、链式前向星具有边集数组和邻接表的功能,属于静态表,不需要频繁地创建节点,应用起来十分灵活。
先看这个例子:
输入
第一行两个数 n,m,分别为顶点数和边数;
第 2~m+1 行,每行三个数,分别为 a,b,c,为一条边的两个端点和这条边的权值。
输出
输出 2*m 行,按顺序输出每个顶点及其连接的边,还有权值。
样例输入
5 7
1 2 6
1 4 8
1 5 9
1 3 7
2 4 4
3 5 5
4 5 2
样例输出
(1,3) 7
(1,5) 9
(1,4) 8
(1,2) 6
(2,4) 4
(2,1) 6
(3,5) 5
(3,1) 7
(4,5) 2
(4,2) 4
(4,1) 8
(5,4) 2
(5,3) 5
(5,1) 9
解题思路
这种存储信息的方式是一种链式结构,定义一个结构体:
struct node
{
int to;//代表当前点经过这条边可以到达的点
int weight;//这条边的权值
int next;//这条边的编号-1(代表上一条边的编号)
};
然后定义一个 first 数组, 它的下标代表顶点编号,然后对应的值代表在图中这个顶点连接有多少条边。
例如:
可以通过 first 数组下标对应的数字,找到该编号顶点连接的边所在的区域。
代码如下:
#include<stdio.h>
struct node//结构体
{
int to;//代表当前点经过这条边可以到达的点
int weight;//这条边的权值
int next;//这条边的编号-1(代表上一条边的编号)
};
int cnt,first[1000];
struct node k[1000];
void add(int a,int b,int c)//用来存储输入信息的函数
{
cnt++;//边的编号
k[cnt].to=b;
k[cnt].weight=c;
k[cnt].next=first[a];
first[a]=cnt;
}
void visit(int x)//找某一顶点所在的边的信息
{
int i;
for(i=first[x];i!=0;i=k[i].next)
{
printf("(%d,%d) %d\n",x,k[i].to,k[i].weight);
}
}
int main()
{
int n,m,i,j;
int a,b,c;
scanf("%d %d",&n,&m);
for(i=1;i<=m;i++)
{
scanf("%d %d %d",&a,&b,&c);
add(a,b,c);//无向图,不要忘记少存信息
add(b,a,c);
}
for(i=1;i<=n;i++)
{
visit(i);
}
return 0;
}
复杂度
n 为结点数,m 为边数,(a)表示 u 的出度(以 a 为出发点的变数)。
查询是否存在 a 到 b 的边:O((u))
遍历点 a 的所有出边:O((u))
遍历整张图:O(n+m)
空间复杂度:O(m)