c语言数据结构图的存储(邻接表)和深度优先搜索

近期西安的疫情确实严重,今天早上接到学校通知要全体同学回到宿舍隔离,于希望疫情早点过去,同时也致敬那些奋战在一线的防疫战疫人员们。

临近期末,得赶快复习了,今天写一篇关于图的相关东西。

首先是存储了,我所选用的是邻接矩阵的存储方式,

那么所定义的存储结构里面呢要包含以下这几个东西:

1.关于图的顶点信息,说白了也就是顶点的名字,我所选用的是字符型。

2.边的关系,这里面用二维数组的方式进行存储,比如Ai与Aj这两个顶点,如果他们之间存在一条边相连接,那么a[i][j]=w,这里的w代表权值,如果没有边的话,就设置成无限大(这里的无穷大)我是在宏定义里面提前定义好了的.
3.顶点数和边数,因为有了顶点数和边数才能在接下来进行输入.
4.图的类型,我定义的为整形,0为无向图,1为有向图,那么无向图的话a[i][j]=a[j][]i],这一点因该很好想通.
那么接下来看看我定义的结构吧,话不多说,直接上代码了.

#define MAX 10        //定义最大顶点数 
#define INFINITY 65535    // 定义无穷大

typedef struct 
{
	char vexs[MAX];//定义顶点信息
	int arc[MAX][MAX];//定义边关系
	int numVertexes;//定义顶点数
	int numEdges;//定义边数
	int type;//定义有向图还是无向图 
}MGraph;//图

书上讲的一维数组存储顶点信息,二维数组定义边关系也就是这个意思了.
那么在了解搜索之前还需要定义一个一维数组进行关于访问过的顶点的一个标记,大家在看了下面搜索过程就会理解为什么需要这个标记数组了。

         int visited[MAX];//标记已经访问过的顶点
         //0代表还未访问,1代表已经访问过了,在搜索之前记得对它初始化!

那么就来创造一个图吧.

void Create(MGraph * G)
{
	int i,j,k,w;
	printf("请输入图的顶点数和边数:\n");
	scanf("%d%d",&G->numVertexes,&G->numEdges);
	fflush(stdin);
	for(i=0;i<G->numVertexes;++i)
	{
		printf("No.%d个顶点: ",i+1);
		scanf("%c",&G->vexs[i]);//输入顶点的名字
		getchar();
	}
	
	for(i=0;i<G->numVertexes;++i)//初始化边关系矩阵 输入之前都没有关系 
	{
		for(j=0;j<G->numVertexes;++j)
		{
			G->arc[i][j]=INFINITY;//输入之前都没有关系
		}
	}
	
	for(k=0;k<G->numEdges;++k)
	{
		printf("输入边(Vi,Vj)的上下标i,j和权w(空格隔开):");
		scanf("%d%d%d",&i,&j,&w);
		G->arc[i][j]=w;
		if(G->type==0)//判断无向图和有向图 
		{
		 G->arc[j][i]=G->arc[i][j];
		}
	}
} 

那么大家在了解了存储的相关知识后就来看看搜索吧。
搜索的话采用深度优先搜索,在我总结起来就是:
首先图的遍历你得了解:
图的遍历是指从图中某个顶点出发遍历图,访遍图中其余顶点,并且使图中的每个顶点仅被访问一次的过程.

深度优先搜索基本思想:
1.从图中某个顶点V0出发,首先访问V0.
2.找到刚访问过的顶点的第一个未被访问的邻接点,然后访问该顶点。以该顶点为新顶点,重复此步骤,直到刚访问过的顶点没有未被访问的邻接点为止.
3.返回前一个访问过的且仍未有未被访问的邻接点的顶点,找出该顶点的下一个未被访问过的邻接点,访问该顶点。然后执行步骤2.
若是非连通图,则图中一定还有顶点未被访问,要从图中另选一个未被访问的顶点作为起始点,重复上述过程.

这些基本思想类的东西大家就请自行了解吧,看看视频,然后拿笔画画就能想个大概,然后再慢慢进行消化理解,我记得当时刚学链表的时候也是这么学会的。

那么接下来就是搜索的函数了

   //深度优先遍历
void DFS(MGraph G, int i)
{
	int j;
	visited[i]=1;//这个顶点访问过了就给他赋值为1
	printf("%c->",G.vexs[i]);
	for(j=0;j<G.numVertexes;++j)//在这里对与这个顶点相连并且还未访问过的顶点进行搜索 
	{
		if(G.arc[i][j]==1&&!visited[j]) 
		{
			DFS(G,j);
		}
	}
} 

void DFStraverse(MGraph G)
{
	int i;
	for(i=0;i<G.numVertexes;++i)
	{
		visited[i]=0;//搜索标记的初始化
	}
	for(i=0;i<G.numVertexes;++i)
	{
		if(!visited[i])
		{
			DFS(G,i);
		}
	}
}

ok,为了大家能够最终能看清,下来咱们再把输入的邻接表输出,大家一看就懂了.

//为了大家可以看的更加清晰  我们把邻接矩阵也顺便输出一下
void Output(MGraph * G)
{
 int i,j,count=0;
 for(i=0;i<G->numVertexes;++i)
 {
 	printf("\t%c",G->vexs[i]);//先横向输出顶点名
 }
 printf("\n");
 for(i=0;i<G->numVertexes;++i)
 {
 	printf("%4c",G->vexs[i]);//每一行先把顶点信息输出
 	for(j=0;j<G->numVertexes;++j)
 	{
 		printf("\t%d",G->arc[i][j]);//输出每一个顶点的边关系
 		count++;
 		if(count%G->numVertexes==0)//换行的基本操作,,
 		{
 			printf("\n");
 		}
 	}
 }
} 

那么最后就可以用main函数进行调用了.

int main()
{
 MGraph G;
 int i,j;
 printf("输入生成图的类型(无向图0/有向图1):");
 scanf("%d",&G.type);
 Create(&G);
 printf("\n");
 DFStraverse(G);
 printf("\n图遍历完毕");
 printf("\n邻接矩阵的输出:\n");
 Output(&G);
}

下面是完整的代码

#include<stdio.h>
#include<stdlib.h>

#define MAX 10        //定义最大顶点数 
#define INFINITY 65535    // 定义无穷大

typedef struct 
{
 char vexs[MAX];//定义结点信息
 int arc[MAX][MAX];//定义边关系
 int numVertexes;//定义顶点数
 int numEdges;//定义边数
 int type;//定义有向图还是无向图 
}MGraph;//图

int visited[MAX];//标记已经访问过的顶点

void Create(MGraph * G)
{
 int i,j,k,w;
 printf("请输入图的顶点数和边数:\n");
 scanf("%d%d",&G->numVertexes,&G->numEdges);
 fflush(stdin);
 for(i=0;i<G->numVertexes;++i)
 {
 	printf("No.%d个顶点: ",i+1);
 	scanf("%c",&G->vexs[i]);
 	getchar();
 }
 
 for(i=0;i<G->numVertexes;++i)//初始化边关系矩阵 输入之间都没有关系 
 {
 	for(j=0;j<G->numVertexes;++j)
 	{
 		G->arc[i][j]=INFINITY;
 	}
 }
 
 for(k=0;k<G->numEdges;++k)
 {
 	printf("输入边(Vi,Vj)的上下标i,j和权w(空格隔开):");
 	scanf("%d%d%d",&i,&j,&w);
 	G->arc[i][j]=w;
 	if(G->type==0)//判断无向图和有向图 
 	{
 	 G->arc[j][i]=G->arc[i][j];
 	}
 }
} 


//深度优先遍历
void DFS(MGraph G, int i)
{
 int j;
 visited[i]=1;
 printf("%c->",G.vexs[i]);
 for(j=0;j<G.numVertexes;++j)//在这里对与这个顶点相连并且还未访问过的顶点进行搜索 
 {
 	if(G.arc[i][j]==1&&!visited[j]) 
 	{
 		DFS(G,j);
 	}
 }
} 

void DFStraverse(MGraph G)
{
 int i;
 for(i=0;i<G.numVertexes;++i)
 {
 	visited[i]=0;
 }
 for(i=0;i<G.numVertexes;++i)
 {
 	if(!visited[i])
 	{
 		DFS(G,i);
 	}
 }
}


//为了大家可以看的更加清晰  我们把邻接矩阵也顺便输出一下
void Output(MGraph * G)
{
 int i,j,count=0;
 for(i=0;i<G->numVertexes;++i)
 {
 	printf("\t%c",G->vexs[i]);
 }
 printf("\n");
 for(i=0;i<G->numVertexes;++i)
 {
 	printf("%4c",G->vexs[i]);
 	for(j=0;j<G->numVertexes;++j)
 	{
 		printf("\t%d",G->arc[i][j]);
 		count++;
 		if(count%G->numVertexes==0)
 		{
 			printf("\n");
 		}
 	}
 }
} 
int main()
{
 MGraph G;
 int i,j;
 printf("输入生成图的类型(无向图0/有向图1):");
 scanf("%d",&G.type);
 Create(&G);
 printf("\n");
 DFStraverse(G);
 printf("\n图遍历完毕");
 printf("\n邻接矩阵的输出:\n");
 Output(&G);
}




ok 战斗结束,下面可以运行检验一下:

输入生成图的类型(无向图0/有向图1):0
请输入图的顶点数和边数:
5 4
No.1个顶点: 0
No.2个顶点: 1
No.3个顶点: 2
No.4个顶点: 3
No.5个顶点: 4
输入边(Vi,Vj)的上下标i,j和权w(空格隔开):0 1 2
输入边(Vi,Vj)的上下标i,j和权w(空格隔开):1 2 4
输入边(Vi,Vj)的上下标i,j和权w(空格隔开):0 2 6
输入边(Vi,Vj)的上下标i,j和权w(空格隔开):4 3 8

0->1->2->3->4->
图遍历完毕
邻接矩阵的输出:
        0       1       2       3       4
   0    65535   2       6       65535   65535
   1    2       65535   4       65535   65535
   2    6       4       65535   65535   65535
   3    65535   65535   65535   65535   8
   4    65535   65535   65535   8       65535

--------------------------------
Process exited after 91.99 seconds with return value 0
请按任意键继续. . .


ok,本期的分享就讲到这了,感谢大家!如果有错误还请各位及时纠正,希望大家一起进步!
  最后拜托疫情早点过去,我想回家过年!

  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值