图的遍历一般分为两种方法,即深度优先搜索(DFS)与广度优先搜索(BFS).
void dfs(adjlist g, int v0) /*DFS算法核心*/
{
int k;
Node *p;
printf("%3d",v0);
visited[v0] = 1;
p = g.data[v0].firstadj;
while(p)
{
k = p->adjvex;
if(visited[k] == 0)
dfs(g,k);
p = p->next;
}
}
void dfstraver(adjlist g, int v0) /*DFS初始化*/
{
int i ;
for(i = 0 ; i < g.m; i++)
visited[i] = 0 ;
dfs(g,v0);
}
/* 一些结构体的定义
typedef struct Node
{
int adjvex; //顶点位置
struct Node *next;
}Node; /*表结点定义*/
typedef struct VNode
{
int vex;
int indegree; //入度
Node *firstadj;
}vertex; /*邻接表中头顶点定义*/
typedef struct
{
vertex data[100];
int m; // 顶点个数
}adjlist;
*/
算法分析:
按照书上的话来说:DFS遍历类似于树的先根遍历,是树的先根遍历的推广.
首先,以上给出的算法是基于邻接表储存的图的DFS遍历.可以看到,其思想并不是围绕一个结点的各个邻接点展开的.而是选择一个开始的结点后就开始访问邻接点,接着访问该邻接点的邻接点.也就是说,其思想是找一条通路走到底.这也就是把这种算法叫做深度优先搜索的原因了.
其次,由于图的遍历中最需要处理的问题并不是找元素或者它们的关系,这些都能在邻接表中得到很好很直观的体现.反倒是怎么样处理重复元素的问题需要思考. 因为图较之树一个明显的特点就是关系的复杂化.从一对多变成了多对多.随着关系的复杂,遍历随着关系进行下去,势必就会出现很多的重复元素. 而对于重复元素,我们最常想到,也是最常使用的就是采用标志数组--遍历过的就将标志数组对应下标表示的元素值设为1.反之则为0.
将这些必要的前提想清楚以后,应该就会有一个大概的想法了:首先指定一个开始的结点,然后在邻接表中找出这个结点的邻接点.然后判断该结点是否被遍历过.如果遍历过就换下一个邻接点.如果没遍历过就以这个结点为开始的结点继续遍历.这里实际上是递归的思想.