列出连通集

此题考查图的构建(使用邻接矩阵构建或者邻接表构建)与遍历,使用深度优先遍历与广度优先遍历的两种遍历方法

浅谈深度优先与广度优先:

深度优先(DFS)遍历图的方法是,从图中某顶点v出发:

  1. 访问顶点v;
  2. 依次从v的未被访问的邻接点出发,对图进行深度优先遍历;直至图中和v有路径相通的顶点都被访问;

对于深度优先算法,需要使用递归进行,其伪代码如下:

void DFS(起始节点 V)
{
	将起始节点V标记拜访过
	for(V节点的所有邻接节点W)
	{
		if(邻接节点W没有拜访过)
			递归调用DFS(邻接节点W)
	}
}

广度优先(BFS)遍历图的方法是,从图中某顶点v出发:

  1. 访问顶点vi ;
  2. 访问vi 的所有未被访问的邻接点w1 ,w2 , …wk ;
  3. 依次从这些邻接点(在步骤②中访问的顶点)出发,访问它们的所有未被访问的邻接点; 依此类推,直到图中所有访问过的顶点的邻接点都被访问;

对于广度优先算法,需要使用队列完成,其伪代码如下:

void BFS(起始节点 V)
{
	将起始节点V标记拜访过
	将起始节点V压入队列Q
	while(队列Q不空)
	{
		队列Q弹出一个元素W
		for(元素W的所有邻接节点T)
		{
			if(节点T没有被拜访过)
			{
				将节点T标记拜访过
				将节点T压入队列Q
			}
		}
	}
}

题目:

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

输入格式:

输入第1行给出2个整数N(0<N≤10)和E,分别是图的顶点数和边数。随后E行,每行给出一条边的两个端点。每行中的数字之间用1空格分隔。

输出格式:

按照"{ v1 v2… 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 }

思路:

主程序的流程大致如下:

int main()
{
	建立表的邻接矩阵(涉及两个函数,建立空的邻接矩阵,将边的信息插入邻接矩阵)
	深度优先算法遍历(涉及两个函数,基础的深度优先算法,对不同的连通集的遍历)
	重置邻接矩阵
	广度优先算法遍历(涉及两个函数,基础的广度优先算法,对不同的连通集的遍历,其中第一个函数还需要建立队列的相关函数:建立队列,判断队列是否为空,向队列插入一个元素,从队列弹出一个元素)
}

根据主函数,需要定义三种结构体变量:

struct 顶点
structstruct 队列

虽然这样操作很麻烦,但是为了练习C语言,忍了……(在刷题的时候,可以直接定义二维数组直接操作)


实际代码如下:

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

#define MAX 10

typedef int vertex;//定义顶点
typedef int weighttype;//边的权重

//定义顶点结构
typedef struct gnode *ptrtognode;
struct gnode
{
	int Nv;//顶点个数
	int Ne;//边数
	weighttype weight[MAX][MAX];//定义邻接矩阵
	int visit[MAX];//数组记录所有点有没有被访问过
};
typedef ptrtognode Mgraph;//定义的邻接矩阵

//定义边结构
typedef struct edge *ptrtoedge;
struct edge
{
	vertex v1, v2;
	weighttype weight;
};
typedef ptrtoedge Edge;

//定义队列结构
typedef struct queue *ptrtoqueue;
struct queue
{
	vertex que[MAX];//定义队列数组
	int front;//队列的头
	int last;//队列的尾部
};
typedef ptrtoqueue Queue;

//建立邻接矩阵的函数
Mgraph createmgraph(int nv);//创建空的邻接矩阵,只有顶点
void insertedge(Mgraph M, Edge e);//向邻接矩阵插入边
void buildmgraph(Mgraph M, int ne);
//深度优先搜索方法
void DFS(Mgraph M,vertex v);//一次深度优先搜索
void listDFS(Mgraph M);//列出所有的深度优先搜索结果
//清空一次搜索结果
void reset(Mgraph M);
//广度优先搜索需要先定义使用队列的基本操作
Queue createqueue();//创建队列
void inqueue(vertex v,Queue q);//搜索前入队操作
int isempty(Queue q);//判断队列是否为空
vertex outqueue(Queue q);//出队操作
//广度优先搜索方法
void BFS(Mgraph M,vertex v);//广度优先搜索
void listBFS(Mgraph M);//列出所有的广度优先搜索结果

//主函数
int main()
{
	int nv;
	scanf("%d", &nv);
	Mgraph M = createmgraph(nv);//创建一个空的邻接矩阵
	scanf("%d", &M->Ne);//对邻接表的边数进行设置;
	buildmgraph(M, M->Ne);//建立邻接矩阵
	listDFS(M);//列出深度优先的搜索结果
	reset(M);//重置
	listBFS(M);//列出广度优先的搜索结果
	return 0;
}

//相关函数的定义
Mgraph createmgraph(int nv)
{
	Mgraph M;
	M = (Mgraph)malloc(sizeof(struct gnode));
	M->Nv = nv;
	M->Ne = 0;
	int i, j;
	for (i = 0; i < nv; i++)
		for (j = 0; j < nv; j++)
			M->weight[i][j] = 0;
	for (i = 0; i < nv; i++)
		M->visit[i] = 0;
	return M;
}

void insertedge(Mgraph M, Edge e)
{
	M->weight[e->v1][e->v2] = e->weight;
	M->weight[e->v2][e->v1] = e->weight;
	return;
}

void buildmgraph(Mgraph M, int ne)
{
	int i;
	Edge e;
	e = (Edge)malloc(sizeof(struct edge));
	for (i = 0; i < ne; i++)
	{
		scanf("%d %d", &e->v1, &e->v2);
		e->weight = 1;
		insertedge(M, e);
	}
	return;
}

void DFS(Mgraph M,vertex v)
{
	M->visit[v] = 1;//标记访问过
	printf("%d ", v);//打印访问过的元素
	int i;
	for (i = 0; i < M->Nv; i++)
	{
		if (M->visit[i] == 0 && M->weight[v][i] == 1)//如果v的临界点没被访问过
			DFS(M, i);
	}
	return;
}

void listDFS(Mgraph M)
{
	int i;
	for (i = 0; i < M->Nv; i++)
	{
		if (M->visit[i] == 0)
		{
			printf("{ ");
			DFS(M, i);
			printf("}\n");
		}		
	}
	return;
}

void reset(Mgraph M)
{
	int i;
	for (i = 0; i <M->Nv; i++)
		M->visit[i] = 0;
	return;
}

Queue createqueue()//初始化队列
{
	Queue q;
	q = (Queue)malloc(sizeof(struct queue));
	q->front = 0;
	q->last = 0;
	int i;
	for (i = 0; i < MAX; i++)
		q->que[i] = -1;
	return q;
}

void inqueue(vertex v, Queue q)
{
	if (q->last == MAX - 1)return;
	q->que[q->last++] = v;
	return;
}

int isempty(Queue q)
{
	if (q->front == q->last)
		return 1;
	else
		return 0;
}

vertex outqueue(Queue q)
{
	if (isempty(q) == 1)return -1;//如果为空,不能出队
	vertex v = q->que[q->front++];
	return v;
}

void BFS(Mgraph M, vertex v)
{
	Queue q;
	vertex tep;
	q = createqueue();
	inqueue(v, q);//将初始遍历的点放在队列中
	M->visit[v] = 1;
	while (isempty(q) == 0)
	{
		tep = outqueue(q);
		printf("%d ", tep);
		int i;
		for (i = 0; i < M->Nv; i++)
		{
			if (M->visit[i] == 0 && M->weight[i][tep] == 1)
			{
				inqueue(i, q);
				M->visit[i] = 1;
			}
		}
	}
}

void listBFS(Mgraph M)
{
	int i;
	for (i = 0; i < M->Nv; i++)
	{
		if (M->visit[i] == 0)
		{
			printf("{ ");
			BFS(M, i);
			printf("}\n");
		}
	}
	return;
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值