深度优先搜索和广度优先搜索( DFS&BFS )

1、深度优先搜索:图的深度优先搜索(Depth First Search),和树的先序遍历比较类似。简称DFS

它的思想:
(1)、首先选择一个入口,标记,再访问邻接的元素,标记,一直下去,直到没有路可走。
(2)、然后按照原路返回,看到没有被标记的地方就访问并且标记上,知道所有元素都被标记。
(3)、注意要原路返回,不然可能会存在有的元素没有访问到然而已经退出的情况。
深度优先搜索和广度优先搜索( DFS&BFS )_第1张图片
在这个图中,若选择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…依次遍历。

深度优先搜索和广度优先搜索( DFS&BFS )_第2张图片
同样以这个图为例:
(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; WNv; 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)无论问题性质如何不同,利用广度优先搜索法解题的基本算法是相同的,但数据库中每一结点内容,产生式规则,根据不同的问题,有不同的内容和结构,就是同一问题也可以有不同的表示方法。

比较深度优先和广度优先两种搜索法,广度优先搜索法一般无回溯操作,即入栈和出栈的操作,所以运行速度比深度优先搜索算法法要快些.
总之,一般情况下,深度优先搜索法占内存少但速度较慢,广度优先搜索算法占内存多但速度较快,在距离和深度成正比的情况下能较快地求出最优解。因此在选择用哪种算法时,要综合考虑。决定取舍。

你可能感兴趣的:(数据结构与算法)