链式向前星(一个优秀的存储图的数据结构)

在学习图的存储的时候,我们通常会有邻接矩阵和邻接表两种选择,邻接矩阵好写但效率低,邻接表不好写写但效率高,这里有一种优秀的数据结构,那便是用静态链表头插法实现的链式向前星

先给出一下邻接矩阵
邻接矩阵
可以看出有向图中有4个顶点4条边
1 —> 2
1 —> 3
2 —> 4
3 —> 1

那么用链式向前星该怎么存呢?
链图

字丑的见不得人啦,对于每个顶点u,我们都会有h[u]代表其指向的第一个边的idx,然后e[idx]是指边v,w[idx]指边u-v的权重,ne[idx]是指链上的下一条边,当ne[i] = -1时表示链完
对于上面的图
h[1] = 1, e[1] = 3, ne[1] = 0, e[0] = 2, ne[0] = -1;
h[2] = 2, e[2] = 4, ne[2] = -1;
h[3] = 3, e[3] = 1, ne[3] = -1;
h[4] = -1;

刚开始我也觉得难理解,但是敲代加画图加脑海模拟便会了,这个是头插法的静态链表,顶点u指向的多个顶点v都在链表中,而链表头就是h[u]; 当h[u] == -1 || ne[idx] == -1就表示链表到空了,看看代码

定义


// N 表顶点个数 M 表边个数 视题目而定 
const int N = 1010, M = 1e4 + 10; 

//这是有向边 
//e[idx]存的是u指向的顶点v, w[idx]存的是 u - v之间的权重
//ne[idx] 存的是下一顶点所在的下标 h[u] 就是头结点 idx是游标 
int e[M], w[M], ne[M], h[N], idx;

//无向边是特殊的有向边 开双倍 
//int e[M<<1], w[M<<1], ne[M<<1], h[N], idx;

初始化

void init()	//初始化 
{
	idx = 0;					//游标从零开始 
	memset(h, -1, sizeof h);	//将所有头结点置空 
} 

加边操作

void add(int a, int b, int c)	//加边操作
{
	e[idx] = b;		//存顶点值
	w[idx] = c; 	//存边权 
	ne[idx] = h[a];	//存h[a]指向的前驱顶点的下标 
	h[a] = idx++; 	//h[a]指向b所在下标, idx游标往后移动 
} 

总揽

#include <iostream>
#include <cstring> 
using namespace std;

// N 表顶点个数 M 表边个数 视题目而定 
const int N = 1010, M = 1e4 + 10; 

//这是有向边 
//e[idx]存的是u指向的顶点v, w[idx]存的是 u - v之间的权重
//ne[idx] 存的是下一顶点所在的下标 h[u] 就是头结点 idx是游标 
int e[M], w[M], ne[M], h[N], idx;

//无向边是特殊的有向边 开双倍 
//int e[M<<1], w[M<<1], ne[M<<1], h[N], idx;

void init()	//初始化 
{
	idx = 0;					//游标从零开始 
	memset(h, -1, sizeof h);	//将所有头结点置空 
} 

void add(int a, int b, int c)	//加边操作
{
	e[idx] = b;		//存顶点值
	w[idx] = c; 	//存边权 
	ne[idx] = h[a];	//存h[a]指向的前驱顶点的下标 
	h[a] = idx++; 	//h[a]指向b所在下标, idx游标往后移动 
} 

int main()
{
	int n, m; //顶点数(1~n)和权值 
	cin >> n >> m;
	
	init();	//别忘初始化 
	while(m--)
	{
		int a, b, c;
		cin >> a >> b >> c;
		add(a, b, c);	//加边 
	}
	
	for(int i = 1;  i <= n; ++i)	//一个一个顶点遍历 
	{
		for(int j = h[i]; j != -1; j = ne[j])	//遍历顶点指向的边 
			cout << e[j] << "(" << w[j] << ") 	";
		cout << "\n\n";
	}
	
	return 0;
}

遍历结果如下:
在这里插入图片描述

>Tips:有想一起交流学习的可以互关 有错误请指出!

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值