深度优先搜索(Depth First Search)遍历类似于树的先序遍历,是树的先序遍历的推广。
无向图的深度优先搜索算法的过程如下:
首先访问出发顶点v,然后选择一个与v相邻接且未被访问过的顶点w访问之,再从w出发开始进行深度优先搜索。
每当到达一个其所有相邻的邻接顶点都已被访问过的顶点,就从该顶点开始,依次退回到尚有邻接顶点未曾被访问过的顶点u,并从u开始进行深度优先搜索。
这个过程进行到所有顶点都被访问到为止,搜索过程结束。
如果无向图是连通的,搜索结束时就可以得到图中所有顶点的一个序列。
下面是用一个简单的4x4的邻接矩阵存储结构实现的无向无权图a
用邻接矩阵表示为:
存储结构代码表示为
typedef struct
{
VertexType vexs[MaxVertexNum]; //顶点表
EdgeType edges[MaxVertexNum][MaxVertexNum]; //邻接矩阵,即边表
int n,e; //顶点数和边数
}Mgraph;
深度优先搜索可描述为(虚线表示访问顺序)
具体实现的C语言代码如下:
#include<stdio.h>
#define MaxVertexNum 100
typedef char VertexType;
typedef int EdgeType;
typedef struct
{
VertexType vexs[MaxVertexNum]; //顶点表
EdgeType edges[MaxVertexNum][MaxVertexNum]; //邻接矩阵,即边表
int n,e; //顶点数和边数
}Mgraph;
bool visited[MaxVertexNum]; //定义是否被访问数组
void CreateMgraph(Mgraph *G)
{//建立有向无权图G的邻接矩阵存储
printf("请输入顶点数和边数\n");
scanf("%d %d",&(G->n),&(G->e));
int i,j;
printf("请输入 %d 个顶点信息:\n",G->n);
for(i=0; i<G->n; i++)
{
scanf("\n%c",&(G->vexs[i]));
}
for(i=0; i<G->n; i++)
for(j=0; j<G->n; j++)
G->edges[i][j] = 0; //初始化邻接矩阵
printf("请输入每条边所对应的两顶点的序号\n");
for(int k=0;k<G->e; k++)
{
scanf("\n%d,%d",&i,&j);
G->edges[i][j] = 1; //若加入G->edges[j][i],则为无向图的邻接存储建立
}
}
void DFS(Mgraph *G,int i)
{
int j;
visited[i] = true;
printf("%c ",G->vexs[i]); //输出结点
for(j=0; j<G->n; j++)
if(G->edges[i][j]==1 && !visited[j])
DFS(G,j); //对要访问的领接顶点进行递归调用
}
void DFSTraverse(Mgraph *G)
{
int i;
for(i=0; i<G->n; i++)
visited[i] = false; //初始化默认顶点都未被访问
for(i=0; i<G->n; i++)
if(!visited[i])
DFS(G,i);
}
int main()
{
Mgraph G;
CreateMgraph(&G);
printf("深度优先遍历结果为:");
DFSTraverse(&G);
printf("\n");
return 0;
}
运行结果如下:
下面是邻接表实现,图示如下
深度优先搜索的顺序与前面相同,实现如下代码:
#include<stdio.h>
#include<stdlib.h>
#define maxsize 20
typedef char VertexType;
typedef struct node //邻接表结点结构
{
int vertex;
struct node *next;
}GLNode;
typedef struct //顶点数组结构
{
VertexType vexs;
GLNode *firstedge;
}VNode,Vex[maxsize];
typedef struct{
Vex vertices; //邻接表
int n,e; //顶点数和边数
}ALGraph;
bool visited[maxsize]; //定义是否被访问数组
void InitGraph(ALGraph &G)
{//初始化邻接表
printf("请输入顶点个数和边数:\n");
scanf("%d,%d",&(G.n),&(G.e));
int i;
printf("建立顶点表");
for(i=0;i<G.n;i++)
{
fflush(stdin);
G.vertices[i].vexs = getchar(); //建立顶点表
G.vertices[i].firstedge = NULL;
}
}
void AddNode(ALGraph &G)
{//建立边表
GLNode *s;
int i,j,k;
for(k=0;k<G.e;k++)
{
fflush(stdin);
printf("读入(vi-vj)的顶点对序号\n"); //新建邻接结点
scanf("%d,%d",&i,&j);
s = (GLNode*)malloc(sizeof(GLNode));
s->vertex = j;
s->next = NULL;
if(!G.vertices[i].firstedge)
G.vertices[i].firstedge = s; //接在表头
else
{
GLNode *p = G.vertices[i].firstedge;
while(p->next)
p = p->next;
p->next = s;
}
}
}
void Dfs(ALGraph &G,int i)
{
int j;
printf("%c ",G.vertices[i].vexs);
visited[i] = true;
GLNode *p = G.vertices[i].firstedge;
while(p)
{
if(!visited[p->vertex])
Dfs(G,p->vertex); //对要访问的领接顶点进行递归调用
p = p->next;
}
}
void Dfstraverse(ALGraph &G)
{
int i;
for(i=0;i<G.n;i++)
visited[i] = false; //初始化都未曾访问过
for(i=0; i<G.n; i++)
if(!visited[i])
Dfs(G,i);
}
int main()
{
ALGraph G;
InitGraph(G);
AddNode(G);
Dfstraverse(G);
return 0;
}
运行结果: