1、深度优先搜索:图的深度优先搜索(Depth First Search),和树的先序遍历比较类似。简称DFS
它的思想:
(1)、首先选择一个入口,标记,再访问邻接的元素,标记,一直下去,直到没有路可走。
(2)、然后按照原路返回,看到没有被标记的地方就访问并且标记上,知道所有元素都被标记。
(3)、注意要原路返回,不然可能会存在有的元素没有访问到然而已经退出的情况。
在这个图中,若选择1为起始点,则访问顺序可以为:
(1.访问1,然后访问1的邻接点2或者3,这里我们选择3.
(2.然后访问3的邻接点,6或者7,这里选择7.
(3.然后访问7的邻接点 ,发现3.6均被标记,所以按照原路返回到3.
(4.发现3的邻接点1.6.7均被访问,继续返回至1。
(5.1的邻接点2.3,发现2没有被标记,所以访问2.
(6.以此类推,我们可以访问4.8.5
所以,遍历的顺序为:1->3->7->6->2->4->8->5.
根据深度优先搜索遍历出来的顺序不一定是一样的,只要满足规则就行,根据选择的不同邻接可能不一样。
显然,深度优先搜索是一个递归的过程。类似入栈出栈操作,容易爆栈。
对于有向图的深度优先探索的遍历跟无向图类似,就不再赘述。
深度搜索的代码实现:
void DFS( LGraph Graph, Vertex V, void (*Visit)(Vertex) )
{ /* 以V为出发点对邻接表存储的图Graph进行DFS搜索 */
PtrToAdjVNode W;
Visited[V] = true; /* 标记V已访问 */
for( W=Graph->G[V].FirstEdge; W; W=W->Next ) /* 对V的每个邻接点W->AdjV */
if ( !Visited[W->AdjV] ) /* 若W->AdjV未被访问 */
DFS( Graph, W->AdjV, Visit ); /* 则递归访问之 */
}
(2)、广度优先搜索:广度优先搜索算法(Breadth First Search),又称为”宽度优先搜索”或”横向优先搜索”,简称BFS。
它的思路:
广度优先搜索的思路是根据距离首先选定的元素的距离进行遍历,一层一层的往外遍历,类似于树的层序遍历,即根据路径1.2.3…依次遍历。
同样以这个图为例:
(1.首先访问1。
(2.访问2、3(也可以换顺序为3、2)。
(3.然后访问2和3的邻接点4、5、6、7(顺序可以变换)。
(4.然后访问8.
所以遍历的顺序可以为:1->2->3->4->5->6->7->8.
广度优先搜索的遍历类似于队列的操作,先将一个元素入队,然后弹出,弹出的时候将该元素的所有邻接点入队,在弹出,再将弹出的元素的邻接点入队,又因为队列是先进先出的特点,就可以实现类似树的层序遍历。
广度优先搜索的代码实现:
void BFS ( MGraph Graph, Vertex S, void (*Visit)(Vertex) )
{ /* 以S为出发点对邻接矩阵存储的图Graph进行BFS搜索 */
Queue Q;
Vertex V, W;
Q = CreateQueue( MaxSize ); /* 创建空队列, MaxSize为外部定义的常数 */
/* 访问顶点S:此处可根据具体访问需要改写 */
Visit( S );
Visited[S] = true; /* 标记S已访问 */
AddQ(Q, S); /* S入队列 */
while ( !IsEmpty(Q) ) {
V = DeleteQ(Q); /* 弹出V */
for( W=0; W<Graph->Nv; W++ ) /* 对图中的每个顶点W */
/* 若W是V的邻接点并且未访问过 */
if ( !Visited[W] && IsEdge(Graph, V, W) ) {
/* 访问顶点W */
Visit( W );
Visited[W] = true; /* 标记W已访问 */
AddQ(Q, W); /* W入队列 */
}
} /* while结束*/
}
两种遍历的比较:
1.深度优先搜索法特点:
(1)有递归以及非递归两种设计方法。一般的,当搜索深度较小、问题递归方式比较明显时,用递归方法设计好,它可以使得程序结构更简捷易懂。当数据量较大时,由于系统堆栈容量的限制,递归容易产生溢出,用非递归方法设计比较好。
2.广度优先搜索
(1)在产生新的子结点时,深度越小的结点越先得到扩展,即先产生它的子结点。为使算法便于实现,存放结点的数据库一般用队列的结构。
(2)无论问题性质如何不同,利用广度优先搜索法解题的基本算法是相同的,但数据库中每一结点内容,产生式规则,根据不同的问题,有不同的内容和结构,就是同一问题也可以有不同的表示方法。
比较深度优先和广度优先两种搜索法,广度优先搜索法一般无回溯操作,即入栈和出栈的操作,所以运行速度比深度优先搜索算法法要快些.
总之,一般情况下,深度优先搜索法占内存少但速度较慢,广度优先搜索算法占内存多但速度较快,在距离和深度成正比的情况下能较快地求出最优解。因此在选择用哪种算法时,要综合考虑。决定取舍。