图的存储结构 --- 邻接表

本文探讨了在图存储中面对稀疏图时,邻接矩阵存储的低效性,进而介绍了邻接表存储的优势,并通过具体代码实现展示了如何更高效地存储和操作稀疏图。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


图的邻接矩阵存储方式方便实现和操作,但是当遇到图为稀疏图的时候这种邻接矩阵的存储将大部分的存储空间都浪费掉了, 比如有5个顶点但是只有一条弧的稀疏图,他的存储只有一条信息是有用的,如下邻接矩阵的存储:



这个时候只有map[1][0] = 9, 其余的存储空间都没有被利用起来,这时候图的另外一种存储方式就显示出了巨大的优势,那就是图的邻接表存储方式。


邻接表是将一个一维数组和链表结合起来作为图的存储方式, 一维数组存储顶点信息, 顶点数组中每个元素都有一个指向第一个邻接顶点的指针,顶点的所有邻接顶点组成一个单链表。 如下所示为无向图的单链表存储方式:




从存储示意图可以看出来, 邻接表的每个顶点都有一个data域和一个指向第一个邻接顶点(其实任何一个邻接顶点都可以称之为第一个)域两部分组成, data域负责存储当前顶点的信息,而第一个邻接顶点域则是该顶点邻接表的第一个头结点。每一个邻接顶点域都包含一个自己顶点信息(自己在顶点数组中的下标)和一个next指针指向下一个邻接顶点。有了这样一个结构,我们想要知道两个节点是否相通则可以遍历对于顶点的链表看是否存在第二个节点即可,当然有向图只需要遍历起点顶点的链表,无向图则不用区分这些。说道有向图,我们要注意一点的是,有向图的邻接表存储都是用弧尾到弧首的放心进行存储,比如下面所示:



当然你也可以使用相反的方式存储,从弧首到弧尾进行逆向存储,我们称这种方式为逆邻接表存储方式,方法类似不在重复复述介绍,有兴趣的可以在纸上画画,很容易就能弄出来。下面看代码的具体实现:

typedef int EdgeType;
typedef int VertexType;
#define MAXVEERTEX 100

typedef struct edge			// 边表结点
{
	int ver_index;			// 邻接顶点域 说明邻接顶点在数组中的下标
	edge* next;				// 下一个邻接顶点域
}EdgeNode;


typedef struct vertex		// 顶点表结构
{
	VertexType ver_noee;	// 顶点信息
	EdgeNode* first_vertex;	// 顶点链表
}VertexNode, AdjList[MAXVEERTEX];

typedef struct graph
{
	AdjList list;
	int ver_num, edge_num;
}Graph;

void create_adjlist_graph(Graph* g)
{
	cout << "Input graph vertexs and edges :" << endl;
	cin >> g->ver_num >> g->edge_num;

	for (int i = 0; i < g->ver_num; i++)
	{
		cout << " Input graph vertex info" << endl;
		cin >> g->list[i].ver_noee;
		g->list[i].first_vertex = NULL;
	}

	
	int val;
	VertexType vi, vj;
	EdgeNode* node = NULL;

	for (int i = 0; i < g->edge_num; i++)
	{
		cout << "input vertex and edge info for example(vi vj x)" << endl;
		cin >> vi >> vj >> val;
		node = (EdgeNode*) malloc(sizeof(EdgeNode));
		if (node == NULL)  exit(0);

		node->ver_index = vj;
		node->next = g->list[vi].first_vertex;
		g->list[vi].first_vertex = node;

		node = (EdgeNode*) malloc(sizeof(EdgeNode));
		if (node == NULL)  exit(0);
		node->ver_index = vi;
		node->next = g->list[vj].first_vertex;
		g->list[vj].first_vertex = node;
	}
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值