列出图的连通集 (25分) (数据结构)(C语言实现)

给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集。假设顶点从0到N−1编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。

输入格式:
输入第1行给出2个整数N(0

输出格式:
按照"{ v
​1
​​ v
​2
​​ … v
​k
​​ }"的格式,每行输出一个连通集。先输出DFS的结果,再输出BFS的结果。

输入样例:

8 6
0 7
0 1
2 0
4 1
2 4
3 5

输出样例:

{ 0 1 4 2 7 }
{ 3 5 }
{ 6 }
{ 0 1 2 7 4 }
{ 3 5 }
{ 6 }

本题目主要是练大家对于图的遍历,一种是广度优先遍历,一种是深度优先遍历。
对于这道题目来说我们要用邻接图来表示,即二维数组。
广度优先遍历是把这个点的相邻部分全访问完,然后以此类推,每遇到一个点,我们就去遍历这个点的周围点。

而深度优先遍历则是找到一个点,再找一个点不断深入下去。

各有各的好处,如果你想要找的点在你附近,那么我们可以采用广度优先遍历,而你想要的点在右下角,我们采取深度优先遍历。

我们首先给出结构体的定义

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define Max 10
struct GNode
{
	int Nv;//顶点
	int Ne;//边
	int a[Max][Max];//存的哪些点是互通的
};
typedef struct GNode *PtrtoG;
int s[Max]={0};//没访问过的点赋值为0,当访问过,则设置为1

需要实现的函数

PtrtoG create(int N,int E);
void BFSshow(PtrtoG G);/*广度优先遍历*/
void BFS(PtrtoG G,int N);
void DFSshow(PtrtoG G);/*深度优先遍历*/
void DFS(PtrtoG G,int N);

首先是图的创建

PtrtoG create(int N,int E)
{   
	PtrtoG G;
	G=(PtrtoG)malloc(sizeof(struct GNode));
	G->Nv=N;
	G->Ne=E;
	int i,j,a,b;
	for(i=0;i<Max;i++)
	{
		for(j=0;j<Max;j++)
		{
			G->a[i][j]=0;//初始化数组
		}
	}
	for(i=0;i<E;i++)
	{
		scanf("%d%d",&a,&b);
		G->a[a][b]=G->a[b][a]=1;//对应两点都赋值为1
	}
	return G;
}

广度优先遍历

void BFSshow(PtrtoG G)
{
	int i;
	while(1)
	{
		for(i=0;i<G->Nv;i++)
		{
			if(!s[i])//哪个点为0,没访问过,退出循环
			break;
		}
		if(i==G->Nv)//所有节点都访问过了
		break;
		printf("{");
		BFS(G,i);//到BFS函数中打印并且访问
		printf(" }\n");
	}
}
void BFS(PtrtoG G,int N)
{
    int t,i;
	int queue[500];//因为要把访问的这个点的周围点都存起来,所以要用队列
	int front=0,rear=0;
	queue[++rear]=N;
	s[N]=1;
	while(front!=rear)//进入循环
	{
		t=queue[++front];//出队列
		printf(" %d",t);
		for(i=0;i<G->Nv;i++)
		{
			if(G->a[t][i]&&!s[i])//没被访问过
			{
				queue[++rear]=i;//入队
				s[i]=1;//这个点被访问了
			}
		}
	}
}

深度优先遍历(比BFS更简单点)

void DFSshow(PtrtoG G)
{
	int i;
	while(1)
	{
		for(i=0;i<G->Nv;i++)
		{
			if(!s[i])
				break;
		}
		if(i==G->Nv)
			break;
		printf("{");
		DFS(G,i);//到DFS函数中访问并且打印
		printf(" }\n");
	}
}
void DFS(PtrtoG G,int n)
{
	int i;
	printf(" %d",n);//直接打印
	s[n]=1;//这个点被访问了
	for(i=0;i<G->Nv;i++)
	{
		if(G->a[n][i]&&!s[i])//这个点和另一个点有通路,且那个点没被访问过,循环进入DFS函数中打印并访问
		{
			DFS(G,i);
		}
	}
}

主函数入口

int main()
{
	int i,N,E;
	scanf("%d%d",&N,&E);
	PtrtoG G;
	G=create(N,E);
	DFSshow(G);
	for(i=0;i<Max;i++)//执行过一次遍历,数组中都为1,此时执行下一次遍历需要重新清0.
		{
            s[i]=0;
        }
	BFSshow(G);
	return 0;
}

总代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define Max 10
struct GNode
{
	int Nv;
	int Ne;
	int a[Max][Max];
};
typedef struct GNode *PtrtoG;

PtrtoG create(int N,int E);
void BFSshow(PtrtoG G);
void BFS(PtrtoG G,int N);
void DFSshow(PtrtoG G);
void DFS(PtrtoG G,int N);

int s[Max]={0};
PtrtoG create(int N,int E)
{   
	PtrtoG G;
	G=(PtrtoG)malloc(sizeof(struct GNode));
	G->Nv=N;
	G->Ne=E;
	int i,j,a,b;
	for(i=0;i<Max;i++)
	{
		for(j=0;j<Max;j++)
		{
			G->a[i][j]=0;
		}
	}
	for(i=0;i<E;i++)
	{
		scanf("%d%d",&a,&b);
		G->a[a][b]=G->a[b][a]=1;
	}
	return G;
}
void BFSshow(PtrtoG G)
{
	int i;
	while(1)
	{
		for(i=0;i<G->Nv;i++)
		{
			if(!s[i])
			break;
		}
		if(i==G->Nv)
		break;
		printf("{");
		BFS(G,i);
		printf(" }\n");
	}
}
void BFS(PtrtoG G,int N)
{
    int t,i;
	int queue[500];
	int front=0,rear=0;
	queue[++rear]=N;
	s[N]=1;
	while(front!=rear)
	{
		t=queue[++front];
		printf(" %d",t);
		for(i=0;i<G->Nv;i++)
		{
			if(G->a[t][i]&&!s[i])
			{
				queue[++rear]=i;
				s[i]=1;
			}
		}
	}
}
void DFSshow(PtrtoG G)
{
	int i;
	while(1)
	{
		for(i=0;i<G->Nv;i++)
		{
			if(!s[i])
				break;
		}
		if(i==G->Nv)
			break;
		printf("{");
		DFS(G,i);
		printf(" }\n");
	}
}
void DFS(PtrtoG G,int n)
{
	int i;
	printf(" %d",n);
	s[n]=1;
	for(i=0;i<G->Nv;i++)
	{
		if(G->a[n][i]&&!s[i])
		{
			DFS(G,i);
		}
	}
}
int main()
{
	int i,N,E;
	scanf("%d%d",&N,&E);
	PtrtoG G;
	G=create(N,E);
	DFSshow(G);
	for(i=0;i<Max;i++)
		{
            s[i]=0;
        }
	BFSshow(G);
	return 0;
}

希望大家对于这些基础题也不要轻视,程序员最忌讳只看不动手去做,看会了和自己动手去做完全不是一个概念,希望大家自己敲代码,取得进步!

你可能感兴趣的:(数据结构)