此题考查图的构建(使用邻接矩阵构建或者邻接表构建)与遍历,使用深度优先遍历与广度优先遍历的两种遍历方法
浅谈深度优先与广度优先:
深度优先(DFS)遍历图的方法是,从图中某顶点v出发:
- 访问顶点v;
- 依次从v的未被访问的邻接点出发,对图进行深度优先遍历;直至图中和v有路径相通的顶点都被访问;
对于深度优先算法,需要使用递归进行,其伪代码如下:
void DFS(起始节点 V)
{
将起始节点V标记拜访过
for(V节点的所有邻接节点W)
{
if(邻接节点W没有拜访过)
递归调用DFS(邻接节点W)
}
}
广度优先(BFS)遍历图的方法是,从图中某顶点v出发:
- 访问顶点vi ;
- 访问vi 的所有未被访问的邻接点w1 ,w2 , …wk ;
- 依次从这些邻接点(在步骤②中访问的顶点)出发,访问它们的所有未被访问的邻接点; 依此类推,直到图中所有访问过的顶点的邻接点都被访问;
对于广度优先算法,需要使用队列完成,其伪代码如下:
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… vk }"的格式,每行输出一个连通集。先输出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 顶点
struct 边
struct 队列
虽然这样操作很麻烦,但是为了练习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;
}