给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集。假设顶点从0到N−1编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。
输入格式:
输入第1行给出2个整数N(0
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXVERTEXNUM 100//最大顶点数
typedef int vertex;
typedef struct VNode* PtrToVertex;
struct VNode{//图的定义
int Nv;//顶点数
int Ne;//边数
int G[MAXVERTEXNUM][MAXVERTEXNUM];//以邻接矩阵存储任意两个顶点之间边的情况(无边、有边、边的权重等)
};
typedef PtrToVertex MGraph;
//队列的定义,用于广度优先遍历
typedef struct QU{
int H[MAXVERTEXNUM];
int front;//数组中首元素的下标
int rear;//数组中最后 一个元素的下标
}Queue;
int visit[MAXVERTEXNUM];//用来标记该顶点已被访问过
MGraph CreateGraph(int N);
MGraph BuildGraph(void);
void DFS(MGraph Graph, int v);
void Print(MGraph Graph);
void BFS(MGraph Graph, int s);
int IsEmpty(Queue* Q);
int DeleteQ(Queue* Q);
int main()
{
MGraph Graph;
Graph = BuildGraph();
memset(visit, 0, sizeof(visit));//也可以不要,全局变量在编译时如未定义则初始化为0
Print(Graph);
return 0;
}
//创建一个图并初始化
MGraph CreateGraph(int N)
{
vertex v, w;//表示二位矩阵的行号与列号
MGraph Graph = (MGraph)malloc(sizeof(struct VNode));
Graph->Nv = N;
Graph->Ne = 0;
for(v = 0; v < Graph->Nv; v++){
for(w = 0; w < Graph->Nv; w++){
Graph->G[v][w] = 0;
}
}
return Graph;
}
//主要要做插入边
MGraph BuildGraph(void)
{
int N, result, i;
MGraph Graph;
vertex v1, v2;
QQ: ;
result = scanf("%d", &N);
if(result != 1 || N <= 0 || N > 10){
printf("输入有误!\n请重新输入\n");
goto QQ;
}
Graph = CreateGraph(N);
scanf("%d", &(Graph->Ne));
if(Graph->Ne != 0){
for(i = 0; i < Graph->Ne; i++){
scanf("%d%d", &v1, &v2);
Graph->G[v1][v2] = 1;
Graph->G[v2][v1] = 1;
}
}
return Graph;
}
//深度优先搜索
void DFS(MGraph Graph, int v)
{
/*类似树中的先序遍历,先访问该未被访问的顶点,然后一个一个找它的未被访问的邻接点访问,
当找到邻接点,再重复上述操作,递推再返回
*/
int i;
printf(" %d", v);
visit[v] = 1;
for(i = 0; i < Graph->Nv; i++){
if(!visit[i] && Graph->G[v][i] == 1){
DFS(Graph, i);
}
}
}
void Print(MGraph Graph)
{
//深度优先搜索
int i;
for(i = 0; i < Graph->Nv; i++){
if(visit[i] == 0){
printf("{");
DFS(Graph, i);//它完后,一个连通集已全部遍历过,并且其中每个顶点都已经标记访问过
printf(" }\n");//下一个进来的必定是另一个连通集中某一个元素,作为入口
}
}
memset(visit, 0, sizeof(visit));//将visit[]数组清零
//广度优先搜索
for(i = 0; i < Graph->Nv; i++){
if(visit[i] == 0){
printf("{");
BFS(Graph, i);
printf(" }\n");
}
}
}
//以s为出发点对邻接矩阵存储的图Graph进行BFS搜索
void BFS(MGraph Graph, int s)
{
Queue Q;//该队列我用了数组,有时会用链表
vertex v, w;
Q.front = 0; Q.rear = 0;
/*同样类似层序遍历,在第一个结点入队之前先访问,然后结点入队,结点出队,分别找到它的
邻结点访问,再入队,只要队列不空,一直进行出队、入队
*/
printf(" %d", s);
visit[s] = 1;
Q.H[(Q.rear)++] = s;
while(!IsEmpty(&Q)){
v = DeleteQ(&Q);
for(w = 0; w < Graph->Nv; w++){
if(!visit[w] && Graph->G[v][w] == 1){
printf(" %d", w);
visit[w] = 1;
Q.H[(Q.rear)++] = w;
}
}
}
}
int IsEmpty(Queue* Q)
{
if(Q->front == Q->rear){
return 1;
}else{
return 0;
}
}
int DeleteQ(Queue* Q)
{
return (Q->H[(Q->front)++]);
}