图的深度优先遍历非递归C语言实现(邻接矩阵、邻接表)
基本思想算法步骤时间复杂度运行示例完整源码
图的深度优先遍历非递归C语言实现(邻接矩阵、邻接表)
路漫漫其修远兮,吾将上下而求索。
每次写东西都会有一些感受,然而有一个问题就是总是容易忘记并且禁不住外界的诱惑,也更加认为“娱乐至死”在现在来说是针对一个人的精神。好了,接下来说说这次的论文,刚开始选这个题目是因为自己觉得上课虽然听着还可以,但是下来之后没有去练过,所以感觉就是比较模糊的,就借此机会来试炼并加深自己对这一块的掌握。
真正开始是在要交的前一天,这时候才开始准备代码,网上找了一下,发现都不太符合要求,于是找了最合适的一片博客开始看(下面给出链接)。试代码的时候发现有诸多bug,于是又不得不去加深理解,然后再修改,就这样弄了十多个小时后才差不多符合要求了。感悟还是比较多的,最深的两个就是:多练;但不要盲目的练,要先理解,才能更快得成功。
(原参考代码链接:https://blog.csdn.net/zscfa/article/details/75947816?locationNum=4&fps=1)
本文是将邻接表与邻接矩阵的非递归用一个文件呈现的,若要查看单独的邻接表(点击这里),邻接矩阵(点击这里)。
基本思想
初始化栈输出起始的顶点,起始顶点改为“已访问”的标志,将起始顶点进栈重复一下的操作直至栈为空:
取栈顶元素顶点,存在着未被访问的邻结点W输出顶点W,将顶点W改为“已访问”,将W进栈;否则,当前顶点退栈
算法步骤
邻接矩阵深度优先非递归算法:
void dfs_adjmatrix(MGraph_adjmatrix
* G
, int v
,int a
[][2]){
Stack
*s
=NULL;
printf("邻接矩阵遍历结果:%d",v
);
for(int i
=0;i
<ves
;i
++)
if(v
==a
[i
][1])v
=a
[i
][0];
G
->book
[v
] = 1;
s
=push(s
,a
[v
][0]);
while(s
!=NULL){
int i
,top
;
top
=s
->data
;
for(i
=0; i
< ves
; i
++){
if(G
->e
[top
][i
] != 0 && G
->book
[i
] != 1){
printf("%d",a
[i
][1]) ;
s
=push(s
,a
[i
][0]);
break;
}
}
if(i
== ves
){
s
=pop(s
);
}
}
printf("\n");
}
时间复杂度
邻接矩阵非递归:该算法的时间复杂度为O(n²),n为顶点数。 邻接表非递归:查找邻接点的时间复杂度为O(e),e表示边数。因此以邻接表做储存结构时,深度优先遍历图的时间复杂度为O(n+e)。
运行示例
若有错误之处,欢迎各位提出、指正。
完整源码
#include<stdlib.h>
#include<stdio.h>
#define MAX 100
#define TRUE 1
#define FALSE 0
int ves
,edge
;
typedef struct Stack
{
int data
;
struct Stack
* next
;
}Stack
;
typedef struct
{
int e
[MAX
][MAX
];
int book
[MAX
];
}MGraph_adjmatrix
;
struct Node
{
int adjves
;
struct Node
* next
;
};
typedef struct Node EdgeNode
;
typedef struct VertexNode
{
int ves
;
EdgeNode
* firstedge
;
}VertexNode
,AdjList
[MAX
];
typedef struct
{
AdjList adjlist
;
int book
[MAX
];
}MGraph_adjlist
;
Stack
* push(Stack
* s
,int a
){
Stack
* line
=(Stack
*)malloc(sizeof(Stack
));
line
->data
=a
;
line
->next
=s
;
s
=line
;
return s
;
}
Stack
* pop(Stack
* s
){
if (s
) {
Stack
* p
=s
;
s
=s
->next
;
free(p
);
}
return s
;
}
int createMGraph_adjlist(MGraph_adjlist
*G
,int a
[][2]){
printf("开始创建邻接表\n");
int i
,j
,k
;
int start
,end
,m
,n
;
EdgeNode
*e
;
for(i
= 0; i
< ves
; i
++){
G
->adjlist
[i
].ves
=a
[i
][0];
G
->adjlist
[i
].firstedge
= NULL;
G
->book
[i
]=0;
}
printf("请输入边(用两个顶点表示,空格分开):\n");
for(i
= 0; i
< edge
; i
++){
scanf("%d%d",&m
,&n
);
k
=0;
for(j
=0;j
<ves
;j
++){
if(a
[j
][1]==m
){
start
=j
;
k
++;
}
if(a
[j
][1]==n
){
end
=j
;
k
++;
}
if(j
==ves
-1&&k
<2){
printf("!!!!顶点不存在于顶点表!!!!\n");
return FALSE
;
}
}
e
=(EdgeNode
*)malloc(sizeof(EdgeNode
));
e
->adjves
= start
;
e
->next
= G
->adjlist
[end
].firstedge
;
G
->adjlist
[end
].firstedge
= e
;
e
=(EdgeNode
*)malloc(sizeof(EdgeNode
));
e
->adjves
= end
;
e
->next
= G
->adjlist
[start
].firstedge
;
G
->adjlist
[start
].firstedge
= e
;
}
printf("成功创建邻接表\n");
return TRUE
;
}
void dfs_adjlist(MGraph_adjlist
*G
,int i
,int a
[][2]){
Stack
* s
= NULL;
EdgeNode
*p
;int n
=0;
G
->book
[i
]=1;
s
=push(s
,a
[i
][0]);
printf("邻接表遍历结果:%d",a
[G
->adjlist
[i
].ves
][1]);
p
= G
->adjlist
[i
].firstedge
;
while(s
!=NULL) {
p
= G
->adjlist
[s
->data
].firstedge
;
while(p
){
n
++;
if(G
->book
[a
[p
->adjves
][0]] == 0){
G
->book
[a
[p
->adjves
][0]]=1;
printf("%d",a
[G
->adjlist
[p
->adjves
].ves
][1]);
s
=push(s
,a
[p
->adjves
][0]);
p
= G
->adjlist
[p
->adjves
].firstedge
;
}
else
p
=p
->next
;
}
if(p
== NULL){
s
=pop(s
);
}
}
printf("%d\n",n
);
}
void inputVes(int a
[][2]){
printf("请输入各顶点:\n");
for(int i
= 0; i
< ves
; i
++){
a
[i
][0]=i
;
scanf("%d",&a
[i
][1]);
}
}
int createMGraph_adjmatrix(MGraph_adjmatrix
* G
,int a
[][2]);
void dfs_adjmatrix(MGraph_adjmatrix
* G
, int v
,int a
[][2]);
int main(){
int s
;
MGraph_adjlist G_adjlist
;
printf("已进入邻接表遍历\n请输入顶点数与边数(空格分开):\n");
scanf("%d%d",&ves
,&edge
);
int a
[ves
][2];
inputVes(a
);
if(createMGraph_adjlist(&G_adjlist
,a
)){
printf("请输入开始结点:\n") ;
scanf("%d",&s
);
for (int i
=0;i
<ves
;i
++){
if(s
==a
[i
][1]){
dfs_adjlist(&G_adjlist
,i
,a
);
break;
}
}
}
printf("是否使用邻接矩阵(继续使用请输入1,退出请输入0): ");
scanf("%d",&s
);
if(s
) {
MGraph_adjmatrix G_adjmatrix
;
printf("请输入顶点数与边数(空格分开):\n");
scanf("%d%d",&ves
,&edge
);
int a
[ves
][2];
if(createMGraph_adjmatrix(&G_adjmatrix
,a
)){
printf("请输入开始结点:\n") ;
scanf("%d",&s
);
dfs_adjmatrix(&G_adjmatrix
,s
,a
);
}
}
return 0;
}
int createMGraph_adjmatrix(MGraph_adjmatrix
* G
,int a
[][2]){
int i
,j
,k
;
int start
,end
,m
,n
;
for(i
= 0; i
<ves
; i
++){
for(j
= 0; j
<ves
; j
++){
G
->e
[i
][j
] = 0;
}
G
->book
[i
] = 0;
}
inputVes(a
);
printf("请输入边(用两个顶点表示,空格分开):\n");
for(i
= 0; i
< edge
; i
++){
scanf("%d%d",&m
,&n
);
k
=0;
for(j
=0;j
<ves
;j
++){
if(a
[j
][1]==m
){
start
=j
;
k
++;
}
if(a
[j
][1]==n
){
end
=j
;
k
++;
}
if(j
==ves
-1&&k
<2){
printf("!!!!顶点不存在于顶点表!!!!\n");
return FALSE
;
}
}
G
->e
[start
][end
] = 1;
G
->e
[end
][start
] = 1;
}
printf("邻接矩阵为:\n");
for(i
= 0; i
<ves
; i
++){
for(j
= 0; j
<ves
; j
++){
printf("%d ",G
->e
[i
][j
]);
}
printf("\n");
}
return TRUE
;
}
void dfs_adjmatrix(MGraph_adjmatrix
* G
, int v
,int a
[][2]){
Stack
*s
=NULL;
printf("邻接矩阵遍历结果:%d",v
);
for(int i
=0;i
<ves
;i
++)
if(v
==a
[i
][1])v
=a
[i
][0];
G
->book
[v
] = 1;
s
=push(s
,a
[v
][0]);
while(s
!=NULL){
int i
,top
;
top
=s
->data
;
for(i
=0; i
< ves
; i
++){
if(G
->e
[top
][i
] != 0 && G
->book
[i
] != 1){
printf("%d",a
[i
][1]);
G
->book
[i
] = 1;
s
=push(s
,a
[i
][0]);
break;
}
}
if(i
== ves
){
s
=pop(s
);
}
}
printf("\n");
}