图的遍历 是指从图中的任一顶点出发,对图中的所有顶点访问一次且只访问一次。
图的遍历是图的基本操作之一,很多需要对图中每个顶点依次进行的操作都可以在遍历中完成。图的遍历通常有 深度优先搜索和广度优先搜索 。
深度优先搜索(Depth-First Search)
深度优先搜索的基本思想如下:
1、从图中某个顶点Vi出发,首先访问Vi
2、选择一个与刚访问过的顶点Vi相邻接且未访问过的顶点Vj,然后访问该顶点。以该顶点为新顶点,重复本步骤,直到当前顶点没有未访问的邻接点为止。
3、返回前一个访问过的且仍有未访问的邻接点的顶点,找出并访问该顶点的下一个未访问的邻接点,然后执行步骤 2。
PS:若访问的是非连通图,我们从某个顶点出发进行深度优先搜索后,则该顶点所在的连通分量的所有顶点都将被访问。此时,若图中还有顶点未访问,则另选图中一个未访问的顶点作为起始点,重复上述深度优先搜索过程,直至图中所有顶点均访问过为止。
对图进行深度优先搜索时,按访问顶点的先后次序得到的顶点的序列称为图的深度优先搜索序列,简称DFS序列。一个图的DFS序列可能不唯一,它与所采用的算法的存储结构和初始出发点密切相关。
邻接表版的DFS
完整代码
#include<stdio.h>
#include<malloc.h>
#define max 100
typedef struct node
{
int adjvex;
struct node*next;
}arcnode;
typedef struct
{
int vertex;
arcnode*firstarc;
}vexnode;
vexnode adjlist[max];
int creatadjlist()
{
arcnode*ptr;
int arcnum,vexnum,k,v1,v2;
printf("input the vexnum,arcnum:");
scanf("%d,%d",&vexnum,&arcnum);
for(k=1;k<=vexnum;k++)
adjlist[k].firstarc=0;
for(k=0;k<arcnum;k++)
{
printf("v1,v2=");scanf("%d,%d",&v1,&v2);
ptr=(arcnode*)malloc(sizeof(arcnode));
ptr->adjvex=v2;
ptr->next=adjlist[v1].firstarc;
adjlist[v1].firstarc=ptr;
ptr=(arcnode*)malloc(sizeof(arcnode));
ptr->adjvex=v1;
ptr->next=adjlist[v2].firstarc;
adjlist[v2].firstarc=ptr;
}
return vexnum;
}
void dfs(int *v)
{
int *w;
arcnode*p;
p=adjlist[*v].firstarc;
printf("%d ",*v);
adjlist[*v].vertex=1;
while(p!=NULL)
{
*w=p->adjvex;
if(adjlist[*v].vertex==0)
dfs(w);
p=p->next;
}
}
int main()
{
int i,n,*v;
arcnode*p;
n=creatadjlist();
printf("the Adjacency List:\n");
for(i=1;i<=n;i++)
{
printf("%d==>",i);
p=adjlist[i].firstarc;
while(p!=NULL)
{
printf("----->%d",p->adjvex);
p=p->next;
}
putchar('\n');
}
printf("the dfs's node v is:");scanf("%d",v);
printf("the dfs:");dfs(v);
return 0;
}
总结
DFS的核心就是不断的访问顶点,本例采用的是较为普遍的做法,设置一个标志(adjlist[v].vertex),若标志等于1则表明访问过,若标志等于0则未访问过,然后再进行递归,当然递归传参记得用引用,不然是不会起到什么效果的。