问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

C++数据结构-图的遍历:DFS深度优先及广度优先详解

创作时间:
作者:
@小白创作中心

C++数据结构-图的遍历:DFS深度优先及广度优先详解

引用
CSDN
1.
https://m.blog.csdn.net/qq_45398836/article/details/143144552

图的遍历是数据结构中的一个重要概念,其中深度优先搜索(DFS)和广度优先搜索(BFS)是最常用的两种遍历算法。本文将详细介绍这两种算法的基本概念、实现步骤、代码示例以及实际应用,帮助读者更好地理解和掌握图的遍历方法。

1、DFS深度优先搜索

1. 图的遍历

在理解DFS算法之前,我们首先需要对什么是遍历进行了解,遍历的概念就是:从某一个点出发(一般是首或尾),依次将数据结构中的每一个数据访问且只访问一遍。

2. DFS简介

DFS(Depth-First-Search,深度优先搜索)算法的具体做法是:从某个点一直往深处走,走到不能往下走之后,就回退到上一步,直到找到解或把所有点走完。

在实现这一个依次的访问顺序时,操作动作存储与数据结构(栈)的思想及其相似,同时也由于栈的性质,我们可以通过递归来简化栈的创建,因此DFS算法的两种做法分别时利用栈或者递归实现。

算法步骤(递归或栈实现)
a)访问指定起始地点。
b)若当前访问顶点的邻接顶点有未被访问的顶点,就任选一个访问。如果没有就回退到最近访问的顶点,直到与起始顶点相通的所有点被遍历完。
c)若途中还有顶点未被访问,则再选一个点作为起始顶点,并重复前面的步骤。

3. 图的DFS

我们直接以案例进行讲解,就本图而言,其访问顺序可以是(不唯一):1-2-4-5-3

首先从1开始,1结点处可以访问2,3两个结点,那么按照我们自定义的优先顺序线访问2结点,此时,2结点有4,5两个结点访问,依旧按次序访问呢4结点,4结点可以访问5结点,5结点无法继续向下访问故结束访问,并回退到4结点,4结点无法没有其他分支且自己已被访问故又退回2结点,2结点的两个分支4,5结点均已被访问,故再退回1结点,此时只有3结点未被访问,访问3结点,最终得到次序:1-2-4-5-3

4.相关代码

DFS算法的相关模板如下:

void dfs()//参数用来表示状态  
{  
    if(到达终点状态)  
    {  
        ...//根据需求添加  
        return;  
    }  
    if(越界或者是不合法状态)  
        return;  
    if(特殊状态)//剪枝,去除一些不需要访问的场景,不一定i俺家
        return ;
    for(扩展方式)  
    {  
        if(扩展方式所达到状态合法)  
        {  
            修改操作;//根据题意来添加  
            标记;  
            dfs();  
            (还原标记);  
            //是否还原标记根据题意  
            //如果加上(还原标记)就是 回溯法  
        }  
  
    }  
}

对于图论而言(代码节选,仅做参考,最主要还请记忆上面的模板那代码):

//从pos点开始,深度遍历无向图
//pos表示当前结点,G表示图,visited[]数组用来表示该节点是否已经访问
void DFS(int pos,pGraph G,int visited[30]){
    node p;
    printf("%d ",pos);//打印深度遍历的点
    visited[pos]=1;//标记为以访问过
    p=G->vertice[pos].firstarc;//将当前点的第一个指针赋值给p
    //是否存在邻接点
    while(p!=NULL) {
        //判断该邻接点是否被遍历过
        if(visited[p->adjvex]==0){
            DFS(p->adjvex,G,visited);
        }
        p=p->next;//后移一位,为之后是否有邻接点做准备
    }
}

5. 实际应用

在最早期的搜索算法,如HTML的搜索,是基于并利用DFS的,现在诸如一些拓扑图,网络等准确且数据量不大的定位运算等依旧应用非常多的DFS算法,同时DFS算法也是算法竞赛入门级别的标准算法,公司的入职考试算法等。

2、BFS广度优先搜索

1. 简介

BFS(Breadth First Search,广度优先搜索,又名宽度优先搜索),与深度优先算法在一个结点“死磕到底“的思维不同,广度优先算法关注的重点在于每一层的结点进行的下一层的访问。

2. BFS算法介绍

BFS算法和核心思路就是:从某个点一直把其邻接点走完,然后任选一个邻接点把与之邻接的未被遍历的点走完,如此反复走完所有结点。类似于树的层序遍历。

BFS的核心就是要把当前在哪作为一个状态存储,并将这个状态交给队列进行入队操作,故而,

算法步骤(用队列实现)
a) 访问指定起始点。
b) 访问当前顶点的邻接顶点有未被访问的顶点,并将之放入队列中。
c) 删除队列的队首节点。访问当前队列的队首,前面的步骤。直到队列为空。
d) 若若途中还有顶点未被访问,则再选一个点作为起始顶点。重复前面的步骤。(针对非连通图)。

3. 案例图示

还是这一份例图,我们直接以案例进行讲解,就本图而言,其访问顺序可以是(不唯一):1-2-3-4-5

首先从1开始,1结点处可以访问2,3两个结点,我们访问并以此把两个结点的访问顺序放入队列,然后按照入队顺序(如2,3),之后我们出队状态2,依次访问2结点的下两个结点(4,5结点),并入队4,5结点,再之后我们出队3结点,并依次访问后续,此时发现所有的结点已经被访问完毕了,可以结束搜索,最后我们得到次序:1-2-3-4-5

4. 相关代码

BFS的模板代码如下:

/**
 * 返回合适的检索数据
 */
int BFS(Node root, Node target) 
{
    Queue<Node> queue;  //创建队列
    int step = 0;       // 当前队列的步骤点
    // initialize
    add root to queue;
    // BFS
    while (queue is not empty) 
    {
        step = step + 1;
        //步数逐渐增加
        int size = queue.size();
        for (int i = 0; i < size; ++i) 
        {
            Node cur = the first node in queue;
            if cur is target
                return step - 1;
            for (Node next : the neighbors of cur) 
            {//这里常用一个二维方向数组实现
                add next to queue;
            }
            remove the first node from queue;
        }
    }
    return -1;          //出错返回值
}

同样提供一份BFS的图论算法节选,代码最核心还是取记忆BFS的模板并根据实际情况的灵活使用,故以下代码仅提供参考

void BFSL(int pos,pGraph G,int visited[30])//从pos点开始进行广度优先遍历无向图
{
    int queue[G->Vnum];//队列辅助BFS遍历
    int head=0,tail=0;//队头、队尾指针
    Arcnode* p;
    queue[tail]=pos;
    visited[pos]=1;//标记遍历过
    tail++;
    while(head!=tail)
    {
        pos=queue[head];//出队操作
        head++;
        printf("%d ",pos);
        p=G->vertice[pos].firstarc;
        while(p!=NULL)
        {
            if(visited[p->adjvex]==0)//判断是否遍历过
            {
                queue[tail]=p->adjvex;//入队操作
                visited[p->adjvex]=1;//标记遍历过
                tail++;
            }
            p=p->next;
        }
    }
}

5. 应用

BFS算法的实际应用场景,最典型的有地图搜索,迷宫寻路等,需要有“状态”以及状态改变场景的搜索算法,同时BFS由于不需要像DFS算法那样回溯,故比DFS效率可能会更高一些。基于BFS算法的该进算法,比如说R星寻路,DBFS(双向广搜)算法等这类改进算法场景被应用在实际游戏设计,GPS导航设计等场景中。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号