数据结构笔记(8)图的深搜和广搜

目录

图与树的转化

深搜

概念

代码实现

广搜

概念

代码实现


图与树的转化

树的介绍中我们曾讲到,任何一个数据结构,我们都可以把它转化成类似树的形式。

例如一维数组或者线性表链表,转化成树的形式,就叫做线段树或者叫树状数组(一种算法)

那么图,也可以转化为类似树的形式。

深搜

概念

深度优先搜索是一种在开发爬虫早期使用较多的方法。它的目的是要达到被搜索结构的叶结点(即那些不包含任何超链HTML文件) 。在一个HTML文件中,当一个超链被选择后,被链接的HTML文件将执行深度优先搜索,即在搜索其余的超链结果之前必须先完整地搜索单独的一条链。深度优先搜索沿着HTML文件上的超链走到不能再深入为止,然后返回到某一个HTML文件,再继续选择该HTML文件中的其他超链。当不再有其他超链可选择时,说明搜索已经结束。 

深搜,全称深度优先搜索,英文简称(dfs),其核心宗旨就是:不撞南墙不回头,不到死路绝不后退。 也就是沿着一条路,一直搜下去,直到尽头才返回。

代码实现

深搜有点类似于二叉树的先序遍历,但又不只是先序遍历,准确来说是先序中序后序的综合体。

深搜的核心思想是回溯法。回溯法介绍

回溯法模板:

void Backtrack(原参数区间/或者参数) {
    if(达到目的/或者撞到“南墙”) {
        存放结果;//或者输出结果,输出最好调用新函数
        return;
    }
 
    进行一些操作(根据实际情况可省去);
 
    for(int i=1;i<=子区间个数(换句话说,也就是父亲节点的度);i++) {//或者子参数个数
 
        做记录;//已经搜过就不再搜了
 
        Backtrack(子区间)//或者下个搜索的参数);//调用子区间或者参数
 
        销毁记录;//搜完,或者撞到南墙,就销毁记录
 
    }
}

但是请注意,不要把深搜和回溯划等号喔!!!深搜只是用到了回溯这种思想,运用回溯这种思想的也不止深搜,同样,深搜也不止用了回溯这一种思想。

深搜是一种偏暴力的算法了(深搜很容易TLE)

那么,图的深搜套用的回溯模板也就是

void Backtrack(当前节点) {
    if(达到目的/或者撞到“南墙”) {
        存放结果;//或者输出结果,输出最好调用新函数
        return;
    }
 
    进行一些操作(根据实际情况可省去);
 
    for(int i=1;i<=当前节点所连接的节点个数;i++) {
 
        记录该节点;//下次就不搜这个节点了
 
        Backtrack(下个节点);
 
        销毁记录;//搜完,或者撞到南墙,就销毁记录
 
    }
}

一般来说,记录节点用bool定义一个叫做vis的数组。

bool vis[10005];//打一个bool类型的vis数组
//vis[1]=0,表示节点1没被记录
//vis[3]=1,表示节点3已经被记录

图的节点,我们采用STL的储存方式(当然,二维数组也可以,STL是便于计数,更方便)

vector<int>G[10005];
//G[i][sum]=j 表示节点i与节点j有一条边相连,并且它是第sum+1条边(下标默认从0开始)
//例如G[1][0]=3 表示节点1与节点3有一条边相连,并且它是第1条边(下标默认从0开始)
//例如G[3][1]=2 表示节点3与节点2有一条边相连,并且它是第2条边(下标默认从0开始)
//例如G[1][2]=2 表示节点1与节点2有一条边相连,并且它是第3条边(下标默认从0开始)
//例如G[2][2]=4 表示节点2与节点4有一条边相连,并且它是第3条边(下标默认从0开始)

所以深搜套用下来也就是:

vector<int>G[N];
bool vis[N];
void Backtrack(int key) {
    if(终止条件) {//根据题目要求,寻找终止条件
        xxxx;
        return;
    }
    for(int i=0;i<G[key].size();i++) {
        //当该点没被搜过
        if(!vis[G[key][i]]) {
            vis[G[key][i]]=1;//做记录
            Backtrack(G[key][i]);//搜索下个节点
            vis[G[key][i]]=0;//搜完销毁记录
        }
    }
}
int main() {
    前置代码;

    vis[key]=1;
    Backtrack(key);

    return 0;
}

广搜

概念

宽度优先搜索算法(又称广度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。

广搜,全称广度优先搜索,又叫宽度优先搜索,英文简称(bfs),它就好比我们拓展城市,总是按照周围一圈一圈的拓展。也可以理解为往水中丢石头,荡起的波纹总是由内向外,一圈一圈从小到大。

代码实现

广搜有点类似于二叉树的层序遍历。所以代码实现也与层序遍历类似,均是打一个队列储存节点。

二叉树层序遍历介绍

queue<int>ans;
ans.push(第一个节点);
vis[第一个节点]=1;
while(!ans.empty()) {
    cout<<ans.front();
    for(int i=0;i<G[ans.front()].size();i++) {
        //当某节点没被搜过
        if(vis[G[ans.front()][i]]==0) {
            ans.push(G[ans.front()][i]);
            vis[G[ans.front()][i]]=1;
        } 
    }
    ans.pop();
}

理论练手项目:

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青衿白首志

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值