深度优先搜索的算法思想:
设初始状态时图中的所有顶点都未被访问,则:
(1):从图中某个顶点i出发,访问i; 然后找到i的一个邻接顶点i1;
(2):从i1出发,深度优先搜索访问和i1相邻接且未被访问的所有顶点;
(3):转(1),直到和i相邻接的所有顶点都被访问为止;
(4):继续选取图中未被访问顶点j作为其实顶点,转(1),直到图中所有顶点都被访问为止;
图的深度优先搜索类似于二叉树的先序遍历。
图的拓扑 结构图及其邻接表表示的存储结构:
假设,从顶点2开始遍历这个图:
(1),访问顶点2;
(2)顶点2的第一个邻接顶点为1,所以访问顶点1;
(3)顶点1的第一个邻接顶点为0,所以访问顶点0;
(4)顶点0的第一个邻接顶点为1,因为1已经被访问过,所以访问这条链表上与1邻接的顶点3,顶点3没有被访问过,所以访问顶点3;
(5)顶点3的第一个邻接顶点为0,因为0已经被访问过,所以访问这条链表上与0邻接的顶点1,又顶点1被访问过,再次访问这条链表上与顶点1邻接的顶点2,又顶点2也被访问过,再次访问这条链表上与2邻接的顶点4,4没有别访问过,所以访问4;
至此,所有顶点都被访问完了,但是由于采用的是递归算法,所以这个算法还没有结束,需要继续回溯到首顶点。
(6)顶点4的第一个邻接顶点为0,被访问过,再次访问这条链表上与0邻接的顶点2,2被访问过,再次访问这条链表上与2顶点邻接的顶点3,顶点3已经被访问过;
(7)然后退回到访问顶点4的顶点3所在的第四条链表;
(8)然后退回到访问顶点3的顶点0所在的第一条链表,第一条链表中顶点3后面的顶点4还没有被访问,也要判断一下是否被访问;经过判断,该顶点已经被访问,这条链表已经访问完了,所以退回到访问顶点0所在的第二条链表;
(9)第二条链表中的顶点2和顶点3之前没有访问,所以判断一下是否被访问过,经过判断,这两个顶点都被访问了,所以退回到访问顶点1的顶点2所在第三条顶点;
(10)顶点2所在的第二条链表中的顶点3和顶点4,在之前都没有被访问,也要判断一下是否被访问,经过比较判断,这两个顶点都被访问了,所以就退回到顶点2;由于顶点2是初始访问的顶点,同时该图又是一个连通图,所以,至此,该图的访问正式结束了。
算法实现;
由算法思想可知,这是一个递归过程,因此,先设计一个从某个顶点为开始深度优先搜索的函数,便于调用。
在遍历整个图时,可以对图中的每一个为被访问的顶点执行所定义的函数。
typedef emnu {FALSE, TRUE} BOOLEAN;
BOOLEAN Visted[MAX_VEX];
void DFS(ALGraph *G, int v)
{
LinkNode *p;
Visited[v] = TRUE;
visit(v);//访问顶点v
p = G->AdjList[v].firstarc;//链表的第一个顶点
while (p != NULL)
{
if (!Visited[p->adjvex])
{
DFS(G, p->ajdvex);
}
//从v的未访问过的邻接顶点出发深度优先搜索
p = p->nextarc;
}
}
//如果是一个非连通图,则使用这个函数
void DFS_traverse_Graph(ALGraph *G)
{
int v;
for (v = 0; v < G->vernum; v++)
{
Visited[v] = FALSE;//访问标志初始化
}
//p = G->AdjList[v].firstarc;
for (v = 0; v < G->vexnum; v++)
{
if (!Visited[v])
DFS(G, v);
}
}