大家好,今天给大家分享一下DFS的实现。DFS指的是从某一节点开始,树的深度遍历。
首先创建邻接矩阵,创建邻接矩阵时:
- 定义无向图的结构体
- 输入顶点个数
- 分别输入顶点
- 对邻接矩阵初始化,初始化边的权值为无穷大
- 输入边的个数n,分别输入n次两顶点及其所连的边的权值,并且找到顶点位置给边赋值
之后便可以进行深度遍历了。创建无向图的过程本人不再赘述。
创建后结果如图:(边权值的最大值为500)
其无向图如下:
邻接矩阵如下:
我们以A为起点,进行DFS遍历,先DFS(A顶点),访问A顶点,再找出A的未访问过的邻接顶点,分别为BCD,但B顶点是A的第一个没有被访问的邻接顶点,所以就访问B,如图:
在邻接矩阵中则如下图表示:
之后将A顶点标记为已经访问,用布尔类型,(因为C语言中没有内置的bool,所以需要自己定义,用int类型也可以,部分代码段如下:)
#define bool char
#define true 1
#define false 0
//布尔类型访问标记
bool visited[VERTEXMAXSIZE];
再DFS(B顶点)并置B为已访问......以此类推,无向图过程如下:
就此,所有顶点都标红,都访问完毕,函数执行完成。
用无向图来表示,即从一个顶点开始,一直访问此顶点的第一个没有被访问的邻接顶点,直到这样的邻接顶点不存在,之后回溯到上一个顶点,寻找下一个未被访问的邻接顶点......
如果要用非递归遍历,我们可以用栈来进行操作。方法与中序法遍历二叉树类似,完整代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
typedef char VertexType;
typedef int EdgeType;
#define WEIGHTMAXSIZE 500
#define VERTEXMAXSIZE 100
#define bool char
#define true 1
#define false 0
typedef struct AdjaencyMatrix{
VertexType vertex[VERTEXMAXSIZE];
EdgeType edge[VERTEXMAXSIZE][VERTEXMAXSIZE];
int VertexNum;
int EdgeNum;
}AMGraph;
//获取定点的位置
int LocateV(AMGraph *G,VertexType v){
int i;
for(i = 0;i<G->EdgeNum;i++){
if(G->vertex[i] == v)
return i;
}
return -1;
}
//创建无向图的邻接矩阵
void CreatAM(AMGraph *G){
//输入顶点个数
int vertexnum,edgenum,i,j;
char v1,v2;
printf("输入顶点个数:");
scanf("%d",&vertexnum);
getchar();
G->VertexNum = vertexnum;
//分别输入顶点
printf("分别输入顶点:(中间不留空格)");
for(i = 0;i<vertexnum;i++){
scanf("%c",&G->vertex[i]);
}
getchar();
//所有边的权初始化
for(i = 0;i<G->VertexNum;i++){
for(j = 0;j<G->VertexNum;j++)
G->edge[i][j] = WEIGHTMAXSIZE;
}
//输入边的个数
printf("输入边的个数:");
scanf("%d",&edgenum);
getchar();
G->EdgeNum = edgenum;
//分别输入两顶点以及边的权值
printf("分别输入两顶点以及边的权值:\n");
for(i = 0;i<edgenum;i++){
int m,n,e;
//输入两个顶点和权值
scanf("%c%c%d",&v1,&v2,&e);
getchar();
//获取定点v1,v2的位置
m = LocateV(G,v1);
n = LocateV(G,v2);
//赋值
G->edge[m][n] = e;
G->edge[n][m] = e;
}
}
//布尔类型访问标记
bool visited[VERTEXMAXSIZE];
//访问函数
void visit(AMGraph G,int Location){
printf("%c--",G.vertex[Location]);
}
//DFS递归遍历
void DFS(AMGraph G,int VLocation){
int i;
//访问v结点,标记结点已经访问
visit(G,VLocation);
visited[VLocation] = true;
//循环访问v顶点的邻接顶点
for(i = 0;i<G.VertexNum;i++){
//顶点没有被访问过,且与v邻接
if((!visited[i]) && G.edge[VLocation][i] != WEIGHTMAXSIZE)
DFS(G,i);
}
}
//找第一个没有被访问的邻接顶点的函数
int FindNotVisit(AMGraph G,int v){
int i;
for(i = 0;i<G.VertexNum;i++){
if(visited[i] == false && G.edge[v][i] != WEIGHTMAXSIZE){
return i;
}
}
return -1;
}
//利用栈进行DFS深度遍历
void StackDFS(AMGraph G,int VLocation){
int stack[VERTEXMAXSIZE];
int w;
int top = 0;
w = VLocation;
visit(G,w);
visited[w] = true;
//找到w的第一个未被访问的邻接顶点,将顶点位置赋给w的位置
while(FindNotVisit(G,w) != -1 || top != 0){
while(FindNotVisit(G,w) != -1){
//找到w的第一个未被访问的邻接顶点
w = FindNotVisit(G,w);
//访问并标记
visit(G,w);
visited[w] = true;
//入栈
stack[top++] = w;
}
if(top != 0){//栈不为空
//出栈
w = stack[--top];
//找顶点的第一个未被访问的邻接顶点
w = FindNotVisit(G,w);
}
}
}
void test01(){
//输入格式如下:
/*
6
ABCDEF
9
BE24
CD5
AC20
CE3
EF9
AD15
CF40
AB11
DF19
*/
int i,j,start;
AMGraph *G;
G = (AMGraph*)malloc(sizeof(AMGraph));
CreatAM(G);
for(i = 0;i<G->VertexNum;i++){
for(j = 0;j<G->VertexNum;j++)
printf("%9d",G->edge[i][j]);
printf("\n");
}
printf("\n\n\n\n递归DFS:\n");
//DFS深度遍历
start = 0;
printf("从第%d个顶点开始:\n",start);
DFS(*G,start);
printf("\n");
//利用栈进行DFS
printf("非递归DFS:\n");
start = 0;
for(i = 0;i<=G->VertexNum;i++)
visited[i] = false;
StackDFS(*G,start);
printf("\n");
}
int main(){
test01();
return 0;
}
运行结果如下:
有错误在品论区留言哦~~~谢谢各位小伙伴!