数据结构—无向图创建邻接矩阵、深度优先遍历和广度优先遍历(C语言版)

一、概念解析:

(1)无向图:

假设图G由两个集合V和E组成,记为G={V , E}。其中V是顶点的有限集合,E是连接V中两个不同顶点的边的有限集合。如果E中的顶点对是有序的,即E中的每条边都是有方向的,则称G是有向图。如果顶点对是无序的,则称G是无向图

在这里插入图片描述

在这里插入图片描述

(2)邻接矩阵:

邻接矩阵主要由:二维数组 实现

如图
在这里插入图片描述

转换成邻接矩阵为:

在这里插入图片描述

二、创建邻接矩阵:

基本每一步都有注释,详细观看,建议画图理解

代码如下:

#define MAXSIZE 100 
//	邻接矩阵 
typedef struct Matrix{
   
	
	int V_Data;		//	顶点数据域 
	int E_Data;		//	边数数据域
	
	int Node[MAXSIZE];	//	存放顶点数据,也就是顶点表 
	int Weight[MAXSIZE][MAXSIZE]; 	//	存放权重,为矩阵中两点有边的标记符号 
	
}MaTrix,*MATRIX;

//	邻接矩阵数据结构体 
typedef struct Edge{
   
	
	int v1;		//	用来存放第一个顶点 
	int v2;		//	用来存放第二个顶点
	int weight;	//	用来存放两点之间的标记符,即为权 
}*EDGE;


//******************** 邻接矩阵*******************//
//	邻接矩阵、顶点和边初始化 
void Init_Matrix(MATRIX S,int Vertex)
{
   	
	S->E_Data = 0;			//	初始化为0条边 
	S->V_Data = Vertex;		//	初始化顶点数 
	
	int i,j;
	for(i=0;i<Vertex;i++)
	{
   
		for(j=0;j<Vertex;j++)
		{
   
			S->Weight[i][j] = 0;
		}
	} 
}

//	开始插入边的权重,即为两个顶点之间边的标记符
void InSerData(MATRIX S,EDGE E)
{
   
	//	将输入的顶点v1、v2之间的边,用权作为标记,在矩阵中表示
	//	这里是无向图,所以边没有方向,需要做标记两次(为v1-v2和v2-v1) 
	S->Weight[E->v1][E->v2] = E->weight;	 
	S->Weight[E->v2][E->v1] = E->weight; 
} 

//	开始插入数据 
void InSerEdge_Data(MATRIX S,int edge,int V)
{
   
	int i,j;
	
	if(edge>0)	//	边数大于0的时候才插入数据 
	{
   
		printf("请输入顶点和权重(空格分隔!)\n");
		for(i=0;i<edge;i++)
		{
   		
			EDGE E;				//分配内存,接受顶点v1,v2和权重(标记符)	
			E = (EDGE)malloc(sizeof(struct Edge));	
			
			scanf("%d %d %d",&(E->v1),&(E->v2),&(E->weight));
			
			if(E->v1 ==E->v2)
			{
   
				printf("无向图邻接矩阵对角线为0,输入错误,结束运行\n");
				exit(-1); 
			}
			
			InSerData(S,E);
		}	
		printf("请输入要定义的顶点,填入顶点表中: \n");
		for(j=0;j<V;j++)
		{
   
			scanf("%d",&(S->Node[j]));
		}
		
	
	}else{
   	
		printf("输入的边数错误"); 
	} 
		
} 

三、深度遍历、广度遍历

(1)深度遍历概念:

在这里插入图片描述

在这里插入图片描述

定义的结构体、数组可看上面代码

深度遍历代码解析:

//*****************	深度优先遍历算法—邻接矩阵 *****************//
void DFS_Begin(MATRIX P,int k,int V)
{
   
	int i;
	flag[k] = 1;	//标记当前顶点,表示已经遍历过

	printf(
  • 142
    点赞
  • 856
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
### 回答1: 建立无向图邻接矩阵存储,可以使用一个二维数组来表示。其中,数组的行和列分别表示图中的节点,而数组中的元素则表示节点之间的连通关系。如果节点i和节点j之间有连通关系,则邻接矩阵中第i行第j列的元素为1;否则为。 深度优先遍历是一种递归的遍历方式,它从图中的某个节点开始,沿着一条路径一直走到底,直到不能再走为止,然后回溯到上一个节点,再选择另外一条路径继续遍历,直到遍历完整个图。 广度优先遍历则是一种迭代的遍历方式,它从图中的某个节点开始,先访问该节点,然后依次访问该节点的所有邻居节点,再依次访问邻居节点的邻居节点,直到遍历完整个图。在广度优先遍历中,需要使用一个队列来存储待访问的节点,以便按照先进先出的顺序进行遍历。 ### 回答2: 建立无向图邻接矩阵指的是将顶点按一定方式编号,然后将边转化为矩阵中的元素。如果两个顶点之间存在一条边,则在对应矩阵元素的位置上标记为1;否则标记为0。建立好邻接矩阵后,我们可以进行深度优先遍历广度优先遍历深度优先遍历:从任一顶点开始,按照某种规则(例如编号增序)依次访问相邻的顶点,并继续向下遍历直到无法继续为止,然后返回上一个顶点继续遍历,直至所有顶点都被访问过为止。在用邻接矩阵存储的无向图上,深度优先遍历的过程可以通过递归实现,具体步骤如下: 1. 从某个顶点v开始访问,我们先将v标记为已访问; 2. 根据邻接矩阵中v所在的行,遍历所有边相连的顶点; 3. 对于每个相邻的顶点,如果它没有被访问过,则递归访问它; 4. 重复步骤2-3,直到所有与v相邻的顶点都被访问过。 广度优先遍历:从任一顶点开始,按照某种规则(例如编号增序)依次访问相邻的顶点,然后再依次访问这些相邻顶点相邻的顶点,直至所有顶点都被访问过为止。在用邻接矩阵存储的无向图上,广度优先遍历的过程可以通过队列实现,具体步骤如下: 1. 从某个顶点v开始访问,我们先将v标记为已访问,并将v入队; 2. 当队列不为空时,取出队头元素u,根据邻接矩阵中u所在的行,遍历所有边相连的顶点; 3. 对于每个相邻的顶点,如果它没有被访问过,则标记为已访问并入队; 4. 重复步骤2-3,直到队列为空。 在实际编码中,我们可以将邻接矩阵存储成一个二维数组(如array[i][j]表示顶点i和顶点j之间是否存在边),然后编写深度优先遍历广度优先遍历的函数。需要注意的是,在状态判断中,我们需要记录每个顶点是否已被遍历过。 ### 回答3: 无向图邻接矩阵存储是一种常见的图形存储结构。它将每个顶点作为矩阵的一行和一列,矩阵中的值表示两个顶点之间的边。对于无向图邻接矩阵是对称的,因为每个边都有相反的方向。如果顶点i和j之间有一条边,则矩阵中的第i行第j列和第j行第i列的值将被设置为1。如果两个顶点之间没有边,则矩阵中的值将为0。 邻接矩阵是用于实现深度优先遍历广度优先遍历的非常方便的数据结构。在深度优先遍历(DFS)中,我们从任意起始点开始遍历,不断深入直到不能再深入为止。我们通过维护一个栈和标记每个节点被访问的状态来实现该算法。在使用邻接矩阵实现时,我们在矩阵中搜索与当前顶点相邻的顶点,将它们加入栈中,然后重复该过程,直到没有更多未访问的节点。 在广度优先遍历(BFS)中,我们从任意起始点开始遍历,逐层遍历直到所有可达节点都被访问。我们通过维护一个队列和标记每个节点被访问的状态来实现该算法。在使用邻接矩阵实现时,我们在矩阵中搜索与当前顶点相邻的顶点,将它们加入队列中,然后处理队列中的下一个节点,重复该过程直到队列为空。 综上所述,使用邻接矩阵实现深度优先遍历广度优先遍历是一种方便且有效的方法,特别是对于小型无向图。但是,在大型无向图中,邻接矩阵可能会占用大量内存,导致效率降低。因此,在这种情况下,邻接表或其他更高级的数据结构可能更适合。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值