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

  1. 都是遍历图,为什么需要两种搜索方式?
  2. 答:因为两种搜索的路径不一样…

例子:
在这里插入图片描述
如上图,在使用深度优先遍历时,假定剑客从左上角进来,到绿色的框格里离开。黑框视为阻隔,白框视为联通,即存在边(Edge)。对于深度优先遍历来说,你要给他规定一种规律,让他一条路走到底,执行递归。规定:剑客会以自己为中心,以上侧为第一个,顺时针,遍历周围的8个格子。结果如下:
在这里插入图片描述
/**************************************************************************************************/
同样这个图,使用广度优先搜索的情况是什么呢?
广度优先,意味着它时一圈一圈搜索的。

1. 自己进队,然后出队,在出队的同时,立马让邻接点入队,即右下的两个白框(不分顺序)
2. 右侧出队,同时,右侧的右侧(记为tmp)进队;
3. 下侧出队,同事,下侧的下侧(记为tmp2)进队;.....依次画圆搜索出口。
结果如下:

在这里插入图片描述
DFS和BFS并没有很大的不同,在本例题中,根据出口的不同,两个搜索的效果也不一样,不能说那个好那个不好,视情况而定。算法的时间复杂度都是相同的。

DFS和BFS的优缺点
如果已知解距离根节点较近,用BFS更好;如果整体上每个节点的边很多,BFS消耗内存会很大。

如果树的解很少并且都很深,那么DFS可能会很慢;如果解很多并且都比较深的话,那么BFS就会很慢。

如果一个问题深度无穷广度有限,那么DFS就没法求解,但BFS可以;反之同理。

/* 邻接表存储的图 - DFS */

void Visit( Vertex V )
{
    printf("正在访问顶点%d\n", V);
}

/* Visited[]为全局变量,已经初始化为false */
void DFS( LGraph Graph, Vertex V, void (*Visit)(Vertex) )
{   /* 以V为出发点对邻接表存储的图Graph进行DFS搜索 */
    PtrToAdjVNode W;
    
    Visit( V ); /* 访问第V个顶点 */
    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 );    /* 则递归访问之 */
}
/* 邻接矩阵存储的图 - BFS */

/* IsEdge(Graph, V, W)检查<V, W>是否图Graph中的一条边,即W是否V的邻接点。  */
/* 此函数根据图的不同类型要做不同的实现,关键取决于对不存在的边的表示方法。*/
/* 例如对有权图, 如果不存在的边被初始化为INFINITY, 则函数实现如下:         */
bool IsEdge( MGraph Graph, Vertex V, Vertex W )
{
    return Graph->G[V][W]<INFINITY ? true : false;
}

/* Visited[]为全局变量,已经初始化为false */
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结束*/
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值