给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集。假设顶点从0到N−1编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。
输入第1行给出2个整数N(0
按照"{ v1 v2… vk}"的格式,每行输出一个连通集。先输出DFS的结果,再输出BFS的结果。
思路:首先建图,这里采用邻接矩阵来存储图,并将其初始化,如果有边就定义为1,建好表之后,再来了解深度优先搜索和广度优先搜索
深度优先搜索(DFS):
他从图中某个顶点v出发,访问此顶点,然后从v的未被访问的邻接点出发深度优先遍历图,直至图中所有和v有路径相通的顶点都被访问到
一般用堆数据结构来辅助实现DFS算法。其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。
直接贴代码
void DFS(MGraph G,int i)
{
int j;
visited[i]=TRUE;
printf("%c",G.vexs[i]);
for(j=0;j<numVertexes;j++)
if(G.arc[i][j]==1&!visited[j])
DFS(G,j);
}
/*邻接矩阵的深度遍历操作*/
void DFSTraverse( MGraph G ){
int i;
for(i=0; i<G.numVetexes; i++)
visited[i]= FALSE;
for(i=0; i<G.numVetexes; i++)
if(!visited[i]){ /*对未访问的顶点调用DFS,若是连通图,只会执行一次 */
DFS(G,i);
}
}
然后是广度优先搜素(BFS):
类似于树的层序遍历,BFS是从根节点开始,沿着树(图)的宽度遍历树(图)的节点。如果所有节点均被访问,则算法中止。一般用队列数据结构来辅助实现BFS算法。
/*邻接矩阵的广度遍历操作*/
void BFSTraverse( MGraph G){
int i,j;
int temp_i;//暂存i的值,为了不忘i的初心,因为后面的语句会改变i的值
Queue Q;
for( i=0; i<G.numVetexes;i++)
visited[i]=FALSE;
InitQueue(&Q); /*初始化队列*/
for( i=0; i<G.numVetexes; i++){ /*对每一个顶点做循环*/
temp_i=i;
if(!visited[i]){
visited[i]=TRUE; /*设置当前结点访问过*/
// printf("{ ");
printf("%d ",G.vexs[i]);
EnQueue(&Q,i); /*将此顶点入队列*/
while( !QueueEmpty(Q) )/*队列中仍有元素*/
{
DeQueue(&Q,&i);//将队中元素出队列,赋值给i
/*判断其他顶点若与当前顶点存在边且未访问*/
for(j=0;j<G.numVetexes;j++){
if(G.arc[i][j] == 1&&!visited[j]){
visited[j]=TRUE;//标记为已访问
printf("%d ",G.vexs[j]);//打印顶点
EnQueue(&Q,j);//将找到的顶点入列
}
}
}
// printf("}\n");
}
i=temp_i; //恢复i的值
}
}
#include
#include
typedef int VertexType;
typedef int EdgeType;
#define MAXVEX 100
#define INFINITY 65535 //用双字节的35535来表示无穷大
typedef int Boolean;
Boolean visited[MAXVEX]; //访问标志的数组
#define TRUE 1
#define FALSE 0
#define ERROR -1
#define MAXSIZE 100
typedef struct{
int data[MAXSIZE];
int front;
int rear;
}Queue;
typedef struct {
VertexType vexs[MAXVEX]; //顶点表
EdgeType arc[MAXVEX][MAXVEX]; //邻接矩阵,可看作边表
int numVetexes,numEdges; //图中当前的顶点数和边数
}MGraph;
/*初始化队列*/
void InitQueue(Queue *Q){
Q->front=0;
Q->rear=0;
}
/*入队列*/
void EnQueue(Queue *Q,int e){
if( (Q->rear+1)%MAXSIZE ==Q->front) /*判断队满*/
return ;
Q->data[Q->rear]=e;
Q->rear=(Q->rear+1)%MAXSIZE;
}
/*出队列*/
void DeQueue(Queue *Q,int *e){
if(Q->front ==Q->rear)//判断队空
return ;
*e = Q->data[Q->front];
Q->front=(Q->front+1)%MAXSIZE;
}
int QueueEmpty(Queue Q){
if(Q.front ==Q.rear)
return 1;
else
return 0;
}
void CreateMGraph( MGraph *G ){
int i,j,k,w;
//printf("输入顶点数和边数:\n");
scanf("%d %d",&G->numVetexes,&G->numEdges);
for( i=0;i<G->numVetexes;i++){
G->vexs[i] = i;
for(j=0;j<G->numVetexes;j++)
G->arc[i][j]=INFINITY;
}
for( k=0;k<G->numEdges;k++){
scanf("%d %d",&i,&j);//输入顶点V1和V2的下标
G->arc[i][j]=1;//默认所有边的权值都为1
G->arc[j][i]=1;
}
}
/*邻接矩阵的深度优先递归算法*/
void DFS(MGraph G,int i){
int j;
visited[i] = TRUE;
printf("%d ",G.vexs[i]);//打印顶点
for( j=0; j<G.numVetexes; j++)
if(G.arc[i][j]== 1 && !visited[j] )
DFS( G, j );
}
/*邻接矩阵的深度遍历操作*/
void DFSTraverse( MGraph G ){
int i;
for(i=0; i<G.numVetexes; i++)
visited[i]= FALSE;
for(i=0; i<G.numVetexes; i++)
if(!visited[i]){ /*对未访问的顶点调用DFS,若是连通图,只会执行一次 */
printf("{ ");
DFS(G,i);
printf("}\n");
}
}
/*邻接矩阵的广度遍历操作*/
void BFSTraverse( MGraph G){
int i,j;
int temp_i;//暂存i的值,因为后面的语句会改变i的值
Queue Q;
for( i=0; i<G.numVetexes;i++)
visited[i]=FALSE;
InitQueue(&Q); /*初始化队列*/
for( i=0; i<G.numVetexes; i++){ /*对每一个顶点做循环*/
temp_i=i;
if(!visited[i]){
visited[i]=TRUE; /*访问*/
printf("{ ");
printf("%d ",G.vexs[i]);
EnQueue(&Q,i); /*将此顶点入队列*/
while( !QueueEmpty(Q) )/*队列中仍有元素*/
{
DeQueue(&Q,&i);
for(j=0;j<G.numVetexes;j++){
if(G.arc[i][j] == 1&&!visited[j]){
visited[j]=TRUE;
printf("%d ",G.vexs[j]);
EnQueue(&Q,j);
}
}
}
printf("}\n");
}
i=temp_i; //恢复i的值
}
}
int main()
{
MGraph G;
CreateMGraph(&G);
DFSTraverse(G);
BFSTraverse(G);
return 0;
}