2022-1-26 数据结构 图的遍历 DFS BFS

24 篇文章 0 订阅
12 篇文章 0 订阅

图的遍历

概念

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

深度优先遍历

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

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

算法步骤(递归或栈实现)

a)访问指定起始地点。

b)若当前访问顶点的邻接顶点有未被访问的顶点,就任选一个访问。如果没有就回退到最近访问的顶点,直到与起始顶点相通的所有点被遍历完。

c)若途中还有顶点未被访问,则再选一个点作为起始顶点,并重复前面的步骤。
在这里插入图片描述
在这里插入图片描述
2访问完后在2的没有被访问的邻接点中选一个(而2号的邻接点存放在邻接矩阵中行下标为2的这行然后顺序去找前提值必须1网则是权值(非0);没有访问过<看visit数组对应的值是不是0>)2–》1,访问1之后修改visited[1]=1–>找1没有被访问过的邻接点(行下标为1个这行依次判断<第一个不行值为0没有边看下一个值是1visited数组值为1访问过了>继续看下一个经过判断3号可以的)1–》3 访问3之后修改visited[3]=1 …3–》5,(5第一个邻接点2访问过了第二个邻接点3也访问过了)–?回退回3–》回退回1–》4–》6–》退到4–》退回1–》退回2(退回起点)访问完毕

DFS访问结果:2–>1–>3–>5–>4–>6(存储结构确定-结果确定)

实现

在这里插入图片描述
在这里插入图片描述

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;//后移一位,为之后是否有邻接点做准备
    }
}

广度优先遍历

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

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

算法步骤(用队列实现)

a) 访问指定起始点。

b) 访问当前顶点的邻接顶点有未被访问的顶点,并将之放入队列中。

c) 删除队列的队首节点。访问当前队列的队首,前面的步骤。直到队列为空。

d) 若若途中还有顶点未被访问,则再选一个点作为起始顶点。重复前面的步骤。(针对非连通图)。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
和树的层次遍历类似(用队列根结点出队将它的左右孩子入队…)设起点为V1,在数组中的0号位置0入队–》V1访问完后出队还要修改visited[1]=1把V1的没有访问过的邻接点入队将1和2入队–》访问完V2把V2出队修改visited[2]=1把V2的没有访问过的邻接点入队(3和4)–》V3(当前队头)访问完出队修改visited[1]=1…(队为空visit数组均为1遍历结束)

算法实现

在这里插入图片描述

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;
        }
    }
}

比较

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值