【C语言】图的邻接表——超详细解析

这篇具有很好参考价值的文章主要介绍了【C语言】图的邻接表——超详细解析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

图的邻接表

我们重点分析一下无向图

邻接表
我们如何将图中所有顶点和边建立起联系?
【C语言】图的邻接表——超详细解析
1.我们发现,V0这个顶点与V1和V3相连,通过右边的邻接表可以看到会出现一个以 V0为头结点的单链表,后面连接的元素就是V1和V3 在顶点数组中的下标
2.这里解释下顶点数组 ,我们事先定义一个数组,用于存放所有的顶点{V0,V1,V2,V3,V4},后期就可以通过下标去找到顶点(每个单链表的头结点)进行 遍历操作

代码实现

step1.创建邻接表的结构体

【C语言】图的邻接表——超详细解析

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#define MaxV 20
//创建邻接表的结构体
typedef struct ArcNode {//边结点
	int adjvex;//该边所指向的顶点在数组中的位置
	struct ArcNode* nextarc;//指向下一条边的指针
}ArcNode;

typedef struct VNode {//顶点信息(顶点作为每个单链表的表头结点)
	int data;
	ArcNode* firstarc;//指向第一条依附该顶点的边的指针
}AdjList[MaxV];
typedef struct {
	AdjList vertices;
	int vexnum, arcnum;//图的当前顶点数和边数
	int kind;//f分成无向图和有向图
}ALGraph;

step2.初始化邻接表

1.首先给出顶点数边数
2.对于每条边,都会关联两个顶点,所以接下里输入被关联的两个顶点
3.通过输入的顶点调用LocateVex函数来找到这两个顶点在顶点数组中的下标
4.创建新结点,采用头插法插入到以每个顶点为头结点的单链表中
5.此处的kind如果为0,那就是无向图,否则均为有向图

void InitALGraph(ALGraph* G,int vexnum,int arcnum) {//顶点个数和边数
	G->vexnum = vexnum;
	G->arcnum = arcnum;
	for (int i = 0; i < G->vexnum; i++) {//给顶点赋值,建立表头结点
		scanf("%d" ,& G->vertices[i].data);
		G->vertices[i].firstarc = NULL;
	}
	for (int k = 0; k < G->arcnum; k++) {
		int v1 = 0;//每条边关联两个顶点
		int v2 = 0;
		scanf("%d%d", &v1, &v2);
		int i = LocateVex(G, v1);
		int j = LocateVex(G, v2);//(i,j)即为对应顶点在vertices数组中的位置
		ArcNode* newNode1 = (ArcNode*)malloc(sizeof(ArcNode));
		newNode1->adjvex = j;
		newNode1->nextarc = G->vertices[i].firstarc;//头插法
		G->vertices[i].firstarc = newNode1;
		//对称
		if (G->kind == 0) {//无向图
			ArcNode* newNode2 = (ArcNode*)malloc(sizeof(ArcNode));
			newNode2->adjvex = i;
			newNode2->nextarc = G->vertices[j].firstarc;//头插法
			G->vertices[j].firstarc = newNode2;
		}
	}
}

step3.实现LocateVex函数

int LocateVex(ALGraph* G, int u)
{
	/* 初始条件: 图G存在,u和G中顶点有相同特征*/
	/* 操作结果: 若G中存在顶点u,则返回该顶点在图中位置;否则返回-1 */
	for (int i = 0; i < G->vexnum; ++i) {
		if (u == G->vertices[i].data) {
			return i;
		}
	}
	return -1;
}

step4.写出打印函数,测试是否正确

void printALGraph(ALGraph* G) {
	int v = 0;
	for (v = 0; v < G->vexnum; v++) {//遍历所有的顶点,分别遍历每个顶点的单链表
		printf("%d ", G->vertices[v].data);
		ArcNode* p;
		for (p = G->vertices[v].firstarc; p; p = p->nextarc) {
			printf("%d ", G->vertices[p->adjvex].data);
		}
		printf("\n");
	}
}

step5.main函数

int main() {          
	int vexnum;
	int arcnum;
	ALGraph* G = (ALGraph*)malloc(sizeof(ALGraph));
	scanf("%d%d", &vexnum, &arcnum);
	int kind = 0;
	scanf("%d", &kind);
	G->kind = kind;
	InitALGraph(G, vexnum, arcnum);
	printf("===========\n");
	printALGraph(G);
	return 0;
}

【C语言】图的邻接表——超详细解析
【C语言】图的邻接表——超详细解析

后面连接顺序不完全一样是输入顺序导致的,但不想影响最后结果,测试是成功
5个顶点,6条边
0表示无向图
0 1 2 3 4表示顶点信息
0 3表示0和3有一条关联边,下面以此类推

【C语言】图的邻接表——超详细解析
【C语言】图的邻接表——超详细解析

完整代码如下

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#define MaxV 20
//创建邻接表的结构体
typedef struct ArcNode {//边结点
	int adjvex;//该边所指向的顶点在数组中的位置
	struct ArcNode* nextarc;//指向下一条边的指针
}ArcNode;

typedef struct VNode {//顶点信息(顶点作为每个单链表的表头结点)
	int data;
	ArcNode* firstarc;//指向第一条依附该顶点的边的指针
}AdjList[MaxV];
typedef struct {
	AdjList vertices;
	int vexnum, arcnum;//图的当前顶点数和边数
	int kind;//f分成无向图和有向图
}ALGraph;

int LocateVex(ALGraph* G, int u)
{
	/* 初始条件: 图G存在,u和G中顶点有相同特征*/
	/* 操作结果: 若G中存在顶点u,则返回该顶点在图中位置;否则返回-1 */
	for (int i = 0; i < G->vexnum; ++i) {
		if (u == G->vertices[i].data) {
			return i;
		}
	}
	return -1;
}

void InitALGraph(ALGraph* G,int vexnum,int arcnum) {//顶点个数和边数
	G->vexnum = vexnum;
	G->arcnum = arcnum;
	for (int i = 0; i < G->vexnum; i++) {//给顶点赋值,建立表头结点
		scanf("%d" ,& G->vertices[i].data);
		G->vertices[i].firstarc = NULL;
	}
	for (int k = 0; k < G->arcnum; k++) {
		int v1 = 0;//每条边关联两个顶点
		int v2 = 0;
		scanf("%d%d", &v1, &v2);
		int i = LocateVex(G, v1);
		int j = LocateVex(G, v2);//(i,j)即为对应顶点在vertices数组中的位置
		ArcNode* newNode1 = (ArcNode*)malloc(sizeof(ArcNode));
		newNode1->adjvex = j;
		newNode1->nextarc = G->vertices[i].firstarc;//头插法
		G->vertices[i].firstarc = newNode1;
		//对称
		if (G->kind == 0) {//无向图
			ArcNode* newNode2 = (ArcNode*)malloc(sizeof(ArcNode));
			newNode2->adjvex = i;
			newNode2->nextarc = G->vertices[j].firstarc;//头插法
			G->vertices[j].firstarc = newNode2;
		}
	}
}

void printALGraph(ALGraph* G) {
	int v = 0;
	for (v = 0; v < G->vexnum; v++) {//遍历所有的顶点,分别遍历每个顶点的单链表
		printf("%d ", G->vertices[v].data);
		ArcNode* p;
		for (p = G->vertices[v].firstarc; p; p = p->nextarc) {
			printf("%d ", G->vertices[p->adjvex].data);
		}
		printf("\n");
	}
}

int main() {          
	int vexnum;
	int arcnum;
	ALGraph* G = (ALGraph*)malloc(sizeof(ALGraph));
	scanf("%d%d", &vexnum, &arcnum);
	int kind = 0;
	scanf("%d", &kind);
	G->kind = kind;
	InitALGraph(G, vexnum, arcnum);
	printf("===========\n");
	printALGraph(G);
	return 0;
}

有些东西看起来很复杂,但仔细一想,不过都是我们学过的东西,需要你耐心发现!!!文章来源地址https://www.toymoban.com/news/detail-429445.html

到了这里,关于【C语言】图的邻接表——超详细解析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 图的创建(详解邻接矩阵和邻接表)

    首先,我们来看一下涉及的知识点: 图 :图 G=(V,E) 由 顶点 集 V 和 边 集 E 组成。每条边对应一个点对 (v,w),其中 v,w 属于 V 。如果图中的点对是有序的,那么该图就是 有向图 ,反之为 无向图 。 邻接点 :若顶点 v 与 w 之间存在一条边,则认为顶点 v 与 w 邻接。 权 :图中

    2024年02月06日
    浏览(40)
  • 【数据结构】邻接矩阵和邻接图的遍历

    本篇文章开始学习数据结构的图的相关知识,涉及的基本概念还是很多的。 本文的行文思路: 学习图的基本概念 学习图的存储结构——本文主要介绍邻接矩阵和邻接表 对每种结构进行深度优先遍历和广度优先遍历 话不多说,狠活献上 等等,先别急,正式学习之前先认识几个

    2024年02月04日
    浏览(50)
  • 图论01-【无权无向】-图的基本表示-邻接矩阵/邻接表

    https://github.com/Chufeng-Jiang/Graph-Theory/tree/main/src/Chapt01_Adjacency 代码有删减 代码有删减 只需要改动一行 adj = new TreeSet[V]; //构造邻接表, V行,V个LinkedList 代码有删减

    2024年02月07日
    浏览(41)
  • 图的存储--邻接矩阵/边集数组/邻接表/链式邻接表/链式前向星

    使用二维数组w[u][v]存储点u到点v的边的权值。 一般应用在点数不多的稠密图 时间复杂度:O(n 2 ) 空间复杂度:O(n 2 ) 边集数组e[i]存储第i条边的「起点、终点、边权」。在kruskal算法中,将边按边权排序,直接存边。 时间复杂度:O(nm) 空间复杂度:O(m) 出边数组e[u][i]存储u的所

    2024年02月02日
    浏览(37)
  • 图的存储结构——邻接表

    回忆邻接矩阵的顺序存储结构,其 内存空间预先分配 , 容易导致空间的溢出或者浪费 。为了使 增减结点方便,提高空间利用效率 ,引入链式存储法——邻接表。 邻接表的组成分为 表头结点表 与 边表 ,如下图所示: 由图可见,每一个边表(单链表)的表头结点存放在表

    2024年02月03日
    浏览(29)
  • 图的存储 —— 邻接矩阵

    图的结构比较复杂,任何两个节点之间都可能有关系。 图的存储分为顺序存储和链式存储。 顺序存储包括邻接矩阵和边集数组, 链式存储包括邻接表、链式前向星、十字链表和邻接多重表。 图的存储 —— 邻接矩阵 邻接矩阵通常采用一个一维数组存储图中节点的信息,采用

    2024年02月06日
    浏览(39)
  • 无向图的邻接矩阵

    无向图的邻接矩阵的定义、表示法、度 定义 逻辑结构分为两部分:V和E集合,其中,V是顶点,E是边。因此,用一个一维数组存放图中所有顶点数据;用一个二维数组存放顶点间关系(边或弧)的数据,这个二维数组称为邻接矩阵。邻接矩阵又分为有向图邻接矩阵和无向图邻

    2024年02月04日
    浏览(36)
  • 图的数据结构,系统学习图的基本概念、定义和建立,学会邻接矩阵、邻接表以及实现六度空间案例,遍历图的方式——广度、深度访问

    图 :G = (V,E) Graph = (Vertex, Edge) V:顶点(数据元素)的有穷非空集合; E:边的有穷集合。 有向图 :每条边都是有方向的     无向图 :每条边都是无方向的   完全图 :任意两点之间都有一条边相连    无向完全图:n个顶点,n(n-1)/2条边 无向完全图:n个顶点,n(n-1)条边 稀疏

    2023年04月22日
    浏览(45)
  • 图的基本操作(邻接矩阵)

    图是比较常用的一种数据结构,我针对期末考试对其进行了大概整理,形成了本文。 整体上是基于文件进行图的建立,有两种文件内容格式,READMODE ==1时,是读入顶点个数,顶点信息以及邻接矩阵,READMODE ==2时,是读入顶点个数,顶点信息,边的个数,边的信息,样例如下:

    2024年02月04日
    浏览(44)
  • 图的邻接矩阵存储及遍历操作

    任务描述 本关任务:要求从文件输入顶点和边数据,包括顶点信息、边、权值等,编写程序实现以下功能。 1)构造无向网G的邻接矩阵和顶点集,即图的存储结构为邻接矩阵。 2)输出无向网G的各顶点和邻接矩阵。 3)输出无向网G中顶点H的所有邻接顶点。 测试说明 平台会对

    2024年02月06日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包