链式前向星

对于存储图的信息有很多种方式,比如邻接二维矩阵或者是直接用几个数组存储。但这些方法对于数据过多的情况会卡壳,毕竟要开辟一个比较大的空间,而且空间的利用效率不高。

或许有些题目给我们的要求是找到某一个顶点所在的边,这样的题目看上去不难,循环存入数据后,再循环查找便可以实现了。但是还有更简单的方法,可以在存入数据的同时找到某一个顶点所在的边。

就是接下来要讲的——链式前向星。

特性

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 为边数,d^{+}(a)表示 u 的出度(以 a 为出发点的变数)。

查询是否存在 a 到 b 的边:O(d^{+}(u))

遍历点 a 的所有出边:O(d^{+}(u))

遍历整张图:O(n+m)

空间复杂度:O(m)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

明里灰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值