数据结构与算法设计分析——常用搜索算法

目录

  • 一、穷举搜索
  • 二、图的遍历算法
    • (一)深度优先搜索(DFS)
    • (二)广度优先搜索(BFS)
  • 三、回溯法
    • (一)回溯法的定义
    • (二)回溯法的应用
  • 四、分支限界法
    • (一) 上界与下界
    • (二) 分支限界法的定义
    • (三)分支限界法的应用
  • 五、回溯法与分支限界法的对比

一、穷举搜索

穷举搜索法也被称为穷举法,其基本思想是将问题的所有的候选解都枚举出来,然后对候选解按照某种顺序进行逐一枚举和检验,并从中找出符合问题要求的候选解作为问题的解。其优点是实现简单且易于理解,适合规模较小的问题,但当问题的规模较大时,由于需要运行问题所有的候选解消耗大量的时间,从而导致算法的效率大大降低。

二、图的遍历算法

图的遍历算法适合无向图和有向图,有两种方法可分为深度优先搜索(DFS)和广度优先搜索(BFS)。

(一)深度优先搜索(DFS)

深度优先搜索的定义
简单地说,图的深度优先搜索可概括为尽可能深地去搜索一个图,是一个递归的过程(需要用到存储),通过遍历邻接表或邻接矩阵的方式深入搜索一个图,直到访问完所有连通的顶点,若当前分支已经访问过,则会回溯到上一个顶点,继续搜索其他分支顶点,直到所有顶点被访问。

  • 递归这一点就类似树的先序遍历,先访问结点,然后递归向外层结点遍历,尽可能深地搜索一个图,都采用回溯算法。

图的深度优先搜索首先选取图中某一顶点vi,访问后,任意选取一个与vi邻接的顶点,且该顶点未被访问,……,继续重复该过程,直到图中所有与vi连通的顶点都被访问到;若还有顶点未被访问到,则另外选取一个未被访问的顶点再次作为起始点,重复以上步骤,继续直至图中所有结点被访问。

例如,对下面这个图,以顶点a为源点对该图进行深度优先遍历,求其一个遍历序列:
在这里插入图片描述
首先,选择与a邻接的任一顶点,由于与a邻接的顶点有b,c,e,可有以下三种访问序列{a,b,……}或{a,c,……}或{a,e,……},如下:
在这里插入图片描述
然后,选择访问顶点d,也可以选择还未被访问的顶点。由于先前选择访问的序列是{a,d},此时访问与顶点d相邻的顶点f,得到序列{a,d,f};再访问与顶点f相邻的顶点c,得到序列{a,d,f,c};由于此时与c邻接的顶点a和f都被访问过,回退到f,继续检查d,与d邻接的顶点也被访问过,……,最后直到顶点d还未被访问,访问它,可得到一个序列{a,e,d,f,c,b}。【序列不唯一】
在这里插入图片描述

可看出a,e,d,f,c这段部分是该图中尽可能深地去搜索一个图的明显体现。

深度优先搜索的空间复杂度和时间复杂度
对于一个图G=(V,E),由顶点集V和边集E组成。
1、空间复杂度

  • 由于DFS算法是一个递归算法,即递归遍历顶点集V,所以通过DFS遍历的空间复杂度为O(|V|)。

2、时间复杂度

  • 时间复杂度取决于图的存储结构,若通过邻接矩阵表示图,则查找顶点的邻接顶点所需时间为O(|V|),总时间复杂度为O(|V2|)(邻接矩阵为方阵n×n);若通过邻接表表示图,则查找所有顶点的邻接顶点所需时间为O(|E|),访问顶点所需时间为O(|V|),即总时间复杂度为O(|V|+|E|)。

(二)广度优先搜索(BFS)

广度优先搜索的定义
广度优先搜索是通过队列来存储顶点实现遍历(队列用于避免重复访问,存放已经访问过的各邻接顶点),可以采用邻接表或邻接矩阵搜索,首先从起始点开始访问,将其邻接顶点依次入队,直到队列为空,从而访问到所有的顶点,即逐层遍历所有的顶点直到遍历完所有节点

  • 逐层遍历这一点就类似树的层序遍历,一层一层向外遍历。

图的广度优先搜索中首先选取一个起始点顶点vi,访问后将其入队并标记为已访问,当队列不为空时检查出队顶点的所有邻接顶点,访问未被访问的邻接顶点并将其入队,……,继续重复该过程,直到图中所有与vi连通的顶点都被访问到;当队列为空时跳出循环,则此时遍历完成。

例如,如下所示的图,从顶点1开始求一个广度优先搜索遍历序列:
在这里插入图片描述
首先,选择与顶点1邻接的所有顶点进行访问,有2和3,可得序列{1,2,3}或{1,3,2};然后,再访问与2和3邻接的其他顶点,直到所有顶点被访问。例如,访问顶点2和3后,访问其邻接顶点4,然后再依次访问顶点4的邻接顶点5和6,最后访问顶点7,得到{1,2,3,4,5,6,7}。【序列不唯一】
广度优先搜索的空间复杂度和时间复杂度
对于一个图G=(V,E),由顶点集V和边集E组成。
1、BFS算法的空间复杂度

  • 与深度搜索所需空间一样,通过BFS遍历的空间复杂度也为O(|V|)。

2、BFS算法的时间复杂度

  • 时间复杂度取决于图的存储结构,若通过邻接矩阵表示图,则查找顶点的邻接顶点所需时间为O(|V|),总时间复杂度为O(|V2|)(邻接矩阵为方阵n×n),这和DFS算法的时间复杂度是一样的;若通过邻接表表示图,则每个顶点都入队一次,即所需时间为O(|V|),搜索顶点的邻接顶点所需时间为O(|E|),其时间复杂度为O(|V|+|E|)。

三、回溯法

(一)回溯法的定义

回溯法用到了上面的深度优先搜索(DFS)的思想,首先,通过穷举所有可能的解(明确搜索范围),从初始状态出发,以深度优先搜索来搜索问题的解,若当前结点不满足,则会退一步回溯到上一个结点尝试其他选择,直到最后找到包含问题解的结点。同样,若问题规模较大时,由于需要穷举所有可能的解,所以此时回溯法的搜索效率较低。【找出解空间树中满足约束条件的所有解】

注:递归算法与回溯法不是同一种思想,回溯法是穷举解空间树来找到满足条件的解的搜索算法思想,而递归是将大问题划分成小问题,然后通过递归以解决小问题来实现最终问题的解,运用了分治的思想。

回溯法的算法框架可分为三部分:
1、针对所给问题,定义问题的解空间;

2、确定易于搜索的解空间组织结构;

3、以深度优先搜索解空间,并在搜索过程中用剪枝函数(隐约束)避免无效搜索。

隐约束分为两种,一种是约束条件,用于判断是否能得到可行解,二是限界条件,用于判断是否能得到最优解。所以,从算法上来看,回溯法是一种带有约束函数(约束条件)或限界函数(限界条件)的深度优先搜索方法。

(二)回溯法的应用

回溯法常用解决排列问题、组合问题、子集问题、路径问题等等。
1、组合问题(组合树/满m叉树)
一组元素中有若干个元素,若将这些元素组合使其一起满足某种性质,该问题的所有组合(解空间树)是一棵满m叉树组合树。例如一个满二叉树如下(m=2):
在这里插入图片描述
例如,一个满m叉树的实例:
对于一个有4个交通信号灯的道路,每个交通信号灯有3种可能的选择(红、黄、绿),需要找出一种选择,使得该道路满足某活动。该场景可以使用满三叉树来表示每个元素(交通信号灯)的选择情况,在满三叉树的每个节点上,有三个子节点,每个子节点代表一个元素(交通信号灯)的选择。如果选择了其中一个元素(交通信号灯),则可以将其对应的子节点标记为已访问,并将该节点加入到结果集中。当遍历完整个满三叉树后,可以得到所有可能的交通信号灯的组合,其中每个组合都满足某种性质,从而找到目标性质满足该活动。

2、排列问题(排列树)
在若干个元素的排列中,确定满足某种性质的一个排列时,该问题的所有排列(解空间树)是一棵排列树。例如,n个元素的排列数为n!(n的阶乘),若n=3,三个元素为{1,2,3},则其排列树如下:
在这里插入图片描述
其中树的根结点为空,表示初始状态。

3、子集问题(子集树)
在若干个元素组成的集合S,确定满足某种性质的一个子集时,该问题的所有子集(解空间树)对应一个子集树。例如,0-1背包问题中,所要找到满足性质的子集为该子集中物品的重量不超过背包容量,且背包内总价值是最大的,该问题的解空间树是一棵子集树。子集树通常有2n个叶结点,其结点总个数为2(n+1)-1,是一棵完全二叉树。

在回溯法中,解向量<x1,x2,…,xn>可以表示为分量取值为{0,1}的比特串,解空间可以组成一颗完全二叉树,这棵搜索树被称为子集树。

四、分支限界法

(一) 上界与下界

对于一个待求解的问题,上界和下界是对问题的可能解进行限制和估计的方法,从而用于解决问题。上界相当于当前最高要求,指问题中的最优解不会超过某个已知值,下界相当于当前最低要求,指问题中的最优解不会低于某个已知值。

利用这一点,可以用于剪枝搜索树的分支,避免对不可能得到最优解的分支进行搜索,从而缩小了搜索空间,达到提高算法效率的目的。

(二) 分支限界法的定义

  • 分支限界法也是一种搜索算法,简单的来说,分支限界法的限界就是利用上界和下界来提高搜索效率。搜索解空间树中利用上界和下界的信息来剪枝搜索树的分支,舍弃导致不可行解或导致非最优解的分支。【找出解空间树中满足约束条件的一个解】

分支限界法中通常采用广度优先搜索(BFS),是以最大收益(最小耗费)的方式来搜索解空间树,其步骤如下:
①首先,将根结点加入活结点表,然后从其中取出,使其成为扩展结点;
②依次生成扩展结点的所有分支,即其孩子结点;
③判断每个孩子结点。通过计算孩子结点的上界和下界,并根据这些界限来决定是否继续搜索该分支,若某个分支的界限满足上界小于或等于下界,则可以剪掉该分支;否则,继续搜索该分支,直到找到满足要求的解或搜索完所有分支(继续通过扩展结点)。

(三)分支限界法的应用

分支限界法的应用场景有:
1、0-1背包问题
2、旅行商问题
旅行商问题指的是在一组给定的城市之间找到最短的路径,使得每个城市恰好被访问一次,最终回到起点。
3、集装箱装载问题
旅行商问题是一个经典的组合优化问题,可以使用分支限界法进行求解。通过搜索所有可能的路径组合,找到总距离最短的一条路径。
4、电路设计中的布线问题
电路设计中的布线问题可以使用分支限界法求解,通过搜索所有可能的布线方式,找到最优解。例如,在M×N的方格中,指定一个方格的中点为a,另一个方格的中点为b,找到a到b的最短路径(布线时只能走直线或直角边)。通过可以把布线的情况剪掉,将能布线的方格加入活结点表,扩展直到找到目标点或活结点表空为止。

五、回溯法与分支限界法的对比

  • 回溯法的优点在于它能够找出所有可能的解,而不仅仅是最优解。而若对于大型问题,回溯法的效率可能较低,因为它需要穷举所有可能的解;分支限界法的优点在于它能够在问题规模较大时,通过剪枝有效地减少搜索空间,从而快速找到最优解,但不能保证找到所有的可能解。
搜索算法名称回溯法分支限界法
搜索解空间树方式深度优先搜索(DFS)广度优先搜索(BFS)
求解解空间树目的找出满足约束条件的所有解找出满足约束条件的一个解
活结点成为扩展结点一次或多次一次

回溯法的适用场景有:n皇后问题、子集树(0-1背包问题、最大团问题)、排列树(旅行商问题、批处理作业调度问题)、组合树(图的m着色问题)等等;

分支限界法的适用场景有:0-1背包问题、旅行商问题、集装箱装载问题、电路设计中的布线问题等等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/161367.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

轻量级 Java 日志组件

日志记录功能在开发中很常用&#xff0c;不仅可以记录程序运行的细节&#xff0c;方便调试&#xff0c;也可以记录用户的行为&#xff0c;是框架中不可或缺的组件。为最大程度复用现有的组件&#xff0c;我们就地取材使用了 JDK 自带的 JUL&#xff08;java.util.logging&#…

学习模拟简明教程【Learning to simulate】

深度神经网络是一项令人惊叹的技术。 有了足够的标记数据&#xff0c;他们可以学习为图像和声音等高维输入生成非常准确的分类器。 近年来&#xff0c;机器学习社区已经能够成功解决诸如对象分类、图像中对象检测和图像分割等问题。 上述声明中的加黑字体警告是有足够的标记数…

手把手教你用C语言写出“走迷宫”小游戏(能看懂文字就会自己敲系列)

目录 设计迷宫地图 设计主角——小球 完整代码 这次教大家编写一个简单的“走迷宫”小游戏&#xff0c;我们可以通过键盘上的‘W’、‘S’、‘A’、‘D’四个键来控制一个“小球”向上&#xff0c;下&#xff0c;左&#xff0c;右移动&#xff0c;目的就是让这个“小球”从起…

Python3语法总结-数据转换②

Python3语法总结-数据转换② Python3语法总结二.Python数据类型转换隐式类型转换显示类型转换 Python3语法总结 二.Python数据类型转换 有时候我们&#xff0c;需要对数据内置的类型进行转换&#xff0c;数据类型的转换。 Python 数据类型转换可以分为两种&#xff1a; 隐式类…

原型网络Prototypical Network的python代码逐行解释,新手小白也可学会!!-----系列4

文章目录 原型网络进行分类的基本流程一、原始代码---计算欧氏距离&#xff0c;设计原型网络&#xff08;计算原型开始训练&#xff09;二、每一行代码的详细解释总结 原型网络进行分类的基本流程 利用原型网络进行分类&#xff0c;基本流程如下&#xff1a; 1.对于每一个样本…

信号完整性分析基础知识之有损传输线、上升时间衰减和材料特性(十):有损传输线在时域中的表现

如果高频衰减大于低频衰减&#xff0c;随着信号传输&#xff0c;上升时间将会增加。上升时间通常定义为边沿在最终值的 10% 到 90% 之间过渡的时间。这假设信号的边缘轮廓看起来有点高斯分布&#xff0c;中间是最快的斜率区域。对于该波形&#xff0c;10%−90% 的上升时间是有意…

MIB 6.1810实验Xv6 and Unix utilities(4)primes

难度: hard/moderate Write a concurrent prime sieve program for xv6 using pipes and the design illustrated in the picture halfway down this page and the surrounding text. This idea is due to Doug McIlroy, inventor of Unix pipes. Your solution should be in …

让你的Mac体验更便捷,快速启动工具Application Wizard为你助力!

亲爱的Mac用户们&#xff0c;你是否经常感到在繁琐的软件启动过程中浪费了太多时间&#xff1f;你是否希望能够以更快的速度找到并启动你所需的应用程序&#xff1f;如果是的话&#xff0c;那么不要犹豫&#xff0c;让我们来介绍一款强大的软件快速启动工具——Application Wiz…

23年宁波职教中心CTF竞赛-决赛

Web 拳拳组合 进去页面之后查看源码&#xff0c;发现一段注释&#xff0c;写着小明喜欢10的幂次方&#xff0c;那就是10、100、1000、10000 返回页面&#xff0c;在点击红色叉叉的时候抓包&#xff0c;修改count的值为10、100、1000、10000 然后分别获得以下信息 ?count1…

Spring面试题:(八)Spring事务

Spring事务概述 Spring事务基于数据库&#xff0c;基于数据库的事务封装了统一的接口。 编程式事务和声明式事务。 声明式事务分为Xml声明式或者注解声明式 实现事务相关的三个类 事务管理器 事务定义 事务状态 XML声明式事务的使用方法 导入坐标配置目标类配置切面 导入…

JS判断是否存在某个元素(includes、indexOf、find、findeIndex、some)(every 数组内所有值是否相同)

方法一&#xff1a;array.includes(searcElement[,fromIndex]) 此方法判断数组中是否存在某个值&#xff0c;如果存在返回true&#xff0c;否则返回false。 searchElement&#xff1a;需要查找的元素&#xff0c;必选。fromIndex&#xff1a;可选&#xff0c;从该索引处开始查…

浏览器页面被恶意控制时的解决方法

解决360流氓软件控制浏览器页面 提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、接受360安全卫士的好意&#xff08;尽量不要选&#xff09;二、拒绝360安全卫士的好意&#xff08;强烈推荐&#xff09;第…

【Vue渲染】 条件渲染 | v-if | v-show | 列表渲染 | v-for

目录 前言 v-if和v-show的区别和联系 v-show和v-if如何选择 条件渲染|v-if|v-show v-if v-if v-else v-if v-else-if v-else template v-show 列表渲染|v-for v-for 前言 本文介绍Vue渲染&#xff0c;包含条件渲染v-if和v-show的区别和联系以及列表渲染v-for v-if和…

“腾易视连”构建汽车生态新格局 星选计划赋能创作者价值提升

11月16日&#xff0c;在2023年广州国际车展前夕&#xff0c;以“腾易视连&#xff0c;入局视频号抓住增长新机会”为主题的腾易创作者大会在广州隆重举办。此次大会&#xff0c;邀请行业嘉宾、媒体伙伴、生态伙伴、视频号汽车领域原生达人等共济一堂&#xff0c;结合汽车行业数…

轻量级的资源授权:基于 OAuth 规范

了解 OAuth 感觉 OAuth 太负盛名了&#xff0c;以至于后来在 OIDC 反而难以企及前辈 OAuth。倒是大家谈论比较多的是 JWT&#xff08;例如https://www.cnblogs.com/lyzg/p/6132801.html&#xff09;&#xff0c;——实际谈 JWT 就是在实现 OIDC&#xff0c;反而 OIDC 大家不怎…

Android跨进程通信,IPC,RPC,Binder系统,C语言应用层调用

文章目录 Android跨进程通信&#xff0c;IPC&#xff0c;RPC&#xff0c;Binder系统&#xff0c;C语言应用层调用&#xff08;&#xff09;1.概念2.流程3.bctest.c3.1 注册服务&#xff0c;打开binder驱动3.2 获取服务 4.binder_call Android跨进程通信&#xff0c;IPC&#xf…

组件插槽,生命周期,轮播图组件的封装,自定义指令的封装等详解以及axios的卖座案例

3.组件插槽 3-1组件插槽 注意 插槽内容可以访问到父组件的数据作用域,因为插槽内容本身就是在父组件模版中定义的 插槽内容无法访问子组件的数据.vue模版中的表达式只能访问其定义时所处的作用域,这和JavaScript的词法作用域是一致的,换言之: 父组件模版的表达式只能访问父组…

计算机毕业设计选题推荐-掌心办公微信小程序/安卓APP-项目实战

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

模块一、任务一.数据分析概述

一、module1 预测未来-总统大选 样本偏差 二、module2 优化现状-化妆品销售 1、数据分析师从业务类型上划分 2、目标&#xff1a;总销量 达到 目标销量 3、固定基本流程 &#xff08;1&#xff09;确定 一、目标值节节升高&#xff0c;是否合理&#xff1f;根据什么定的&…