双向广搜(bfs)

2023-11-08

双向广度优先搜索

广度优先搜索遵循从初始结点开始一层层扩展直到找到目标结点的搜索规则,它只能较好地解决状态不是太多的情况,承受力很有限。如果扩展结点较多,而目标结点又处在较深层,采用前文叙述的广度搜索解题,搜索量巨大是可想而知的,往往就会出现内存空间不够用的情况。双向搜索和A算法对广度优先的搜索方式进行了改良或改造,加入了一定的“智能因素”,使搜索能尽快接近目标结点,减少了在空间和时间上的复杂度。

  (1)搜索过程
  有些问题按照广度优先搜索法则扩展结点的规则,既适合顺序,也适合逆序,于是我们考虑在寻找目标结点或路径的搜索过程中,初始结点向目标结点和目标结点向初始结点同时进行扩展—,直至在两个扩展方向上出现同一个子结点,搜索结束,这就是双向搜索过程。出现的这个同一子结点,我们称为相交点,如果确实存在一条从初始结点到目标结点的最佳路径,那么按双向搜索进行搜索必然会在某层出现“相交”,即有相交点,初始结点一相交点一目标结点所形成的一条路径即是所求路径。

      (2)结点扩展顺序
    双向扩展结点,在两个方向的扩展顺序上,可以轮流交替进行,但由于大部分的解答树并不是棵完全树,在扩展完一层后,下一层则选择结点个数较少的那个方向先扩展,可以克服两个方向结点生成速度不平衡的状态,明显提高搜索效率。

  (3)数据结构
    单向广度优先搜索需建立两个表OPEN和CLOSED,用来存储生成结点和已扩展结点,双向搜索从两个方向进行扩展,我们建立两个二维表OPEN,CLOSED,OPEN[1],CLOSED[1], OPEN[2],CLOSED[2]分别存储两个方向上的生成结点和已扩展结点,OPEN仍然是具有“先进先出”的队列结构。为编程方便,我们采用基于广度优先搜索算法的双向,建立三个二维指针:Q1,Q2,Q3其作用如下:
    Q1[1],Q1[2]:分别指向两个方向上当前待扩展层的第一个结点。
    Q2[1],Q2[2]:分别指两个方向上队尾新产生的结点。
    Q3[1],Q3[2]:分别指向两个方向上下一层的第一个结点位置。
    为了区分当前搜索方向,设方向标志:
    t=1表示处于正向搜索,t=2表示处于逆向搜索。
    Fail—有一个方向搜索失败时,为真,并且结束搜索过程,否则为假。
    I—全局变量,指向当前要扩展的结点。

  (4)算法描述

初始化visited数组,将所有点的值设为false;//visited数组用来保存所有点的访问情况
visited[start]=true;//start为起始点
queue<type> search;//用来保存待搜索点的队列
search.push(start);
while(!search.empty())
{
      v=search.front();
      search.pop();   //弹出一个点处理,用v表示
      for(每一个v的相邻点)
         if(!visited[v]){
            visited[v]=true;
            search.push(v);
         }
}

以上代码部分只是所有点的遍历,为的是理解思想,并没有加入达到终止条件返回步数(这很关键),我会在下面双向广度优先搜索加上。
双向广度优先搜索则是从出发点和目标点分别向后向前搜索,当相遇时则终止。在code时关键问题有:怎么记录当前搜索步数;怎么判断和什么时候判断达到终止条件;搜索时向前向后的顺序。对于搜索函数伪代码(不考虑点的存储结构)如下:

if(start==finish)
      return 0;
初始化visited数组里每个值为0; //这里visited值为1则为向后搜索过的值,为2则为向前搜索过的值
初始化起始点start.step=true; //这里step属性为真则表示为某一搜索步数中的最后一个点,例如对于poj1915中第2步有八个点,只有第八个点的step为true,其余为false
初始化目标点finish.step=true;
visited[start]=true;
visited[finish]=true;
queue<type> frontSearch;       //记录从前向后搜索的队列
queue<type> backSearch;       //记录从后向前搜索的队列
fstep=0;                                    //记录从前向后搜索的步数
bstep=0;                                   //记录从后向前搜索的步数
frontSearch.push(start);
backSearch.push(finish);
while(!frontSearch.empty() || !backSearch.empty())
    {
        if(!frontSearch.empty())
                {
                     do{
                              current=frontSearch.front();//从队列中弹出当前搜索的点
                              frontSearch.pop();
                              for(每一个current的相邻点v){
                                    if(visited[v]==2)
                                          return fstep+bstep+1;//如果遇到了从后向前搜索搜过的点则终止,并且返回总步数
                                    if(!visited[v]){
                                          visited[v]=1;
                                          frontSearch.push(v);
                                    }
                              }
                          }while(!current.step)               //同一步的点已经全部搜完,结束循环
                           fstep++;                                //增加从前向后搜索的步数
                           current=frontSearch.front();
                           frontSearch.pop();
                           current.step=true;
                           frontSearch.push(current);      //将当前步数最后一个点的step属性设为true;

                 }
                  if(!backSearch.empty())
                {
                     do{
                              current=backSearch.front();//从队列中弹出当前搜索的点
                              backSearch.pop();
                              for(每一个current的相邻点v){
                                    if(visited[v]==1)
                                          return fstep+bstep+1;//如果遇到了从前向后搜索搜过的点则终止,并且返回总步数
                                    if(!visited[v]){
                                          visited[v]=2;
                                          backSearch.push(v);
                                    }
                              }
                          }while(!current.step)               //同一步的点已经全部搜完,结束循环
                           bstep++;                                //增加从后向前搜索的步数
                           current=backSearch.front();
                           backSearch.pop();
                           current.step=true;
                           backSearch.push(current);      //将当前步数最后一个点的step属性设为true;

                 }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

双向广搜(bfs) 的相关文章

  • 零基础如何学习Web 安全,如何让普通人快速入门网络安全?

    前言 网络安全现在是朝阳行业 缺口是很大 不过网络安全行业就是需要技术很多的人达不到企业要求才导致人才缺口大 帮助安全学习 免费领取网络安全面试题 学习路线 视频教程 工具 需要可以微信扫描下方CSDN官方认证二维码免费领取 保证100 免
  • C语言之if语句

    C语言之if语句 一 简单形式的if语句可以让程序选择执行一条语句 或者跳过这条语句 实例1 下面我们通过一个简单的代码来判定学生成绩是否合格 include
  • 如何打开iso文件

    iso文件用什么打开 iso文件用什么打开 使用光驱可以打开iso文件 iso文件是一种光盘 CD 上的系统文件格式 因此我们只需要将iso文件写入到光盘当中 然后用光驱打开光盘即可安装iso文件软件了 目前我们常购买的光盘系统盘就是商家将
  • 服务器远程如何修改密码,服务器远程如何修改密码

    服务器远程如何修改密码 内容精选 换一换 本地Windows操作系统主机 推荐使用 方法1 使用RDP文件登录在控制台单击 远程登录 下载RDP文件至本地 运行RDP文件 输入密码 密钥鉴权方式请先获取登录密码 登录远程桌面 详细操作请参考
  • 如何屏蔽百度搜索推广

    这几天大家都在说百度推广的事 笔者没什么好说的 毕竟已经很久没有见过百度推广了 不过说实话 很多时候谷歌搜出来的东西才是我想要的 今天就讲一下如何使用插件屏蔽百度推广 一 工具 1 chrome浏览器 2 Tampermonkey 插件 c
  • 性能优化工具:SQL Profiler

    https www cnblogs com kissdodog p 3398523 html 一 SQL Profiler工具简介 SQL Profiler是一个图形界面和一组系统存储过程 其作用如下 图形化监视SQL Server查询 在
  • Hexo + GitHub 搭建个人博客(二) Hexo monie主题

    前言 hexo theme monie 卡片化设计 安装 Git 安装 在项目的根目录下执行 git clone https gitee com lyboy6 hexo themes monie git themes monie npm 安
  • STM32NVIC中断优先级管理

    目录 抢占优先级响应优先级区别 中断设置相关寄存器 IO unit8 t IP 240 中断优先级控制寄存器组 中断参数初始化函数NVIC Init NVIC InitTypeDef结构体 抢占优先级响应优先级区别 抢占优先级高的可以打断正
  • 常用的LaTeX公式用法

    常用的LaTeX公式用法 常用的latex公式用法 常用的latex公式用法 加法 效果 减法 效果 乘法 叉乘 times 例子 a b a times b a b 效果 a b 乘法 点乘 cdot
  • 本地Linux服务器安装宝塔面板,并内网穿透实现公网远程登录

    文章目录 前言 1 安装宝塔 2 安装cpolar内网穿透 3 远程访问宝塔 4 固定http地址 5 配置二级子域名 6 测试访问二级子域名 转发自CSDN远程穿透的文章 Linux安装宝塔 并实现公网远程登录宝塔面板 内网穿透 前言 宝
  • MySQL数据库基本操作-DQL

    文章目录 一 基本查询 二 运算符 2 1 算术运算符 2 2 位运算符和逻辑运算符 2 3 比较运算符 三 排序查询 四 聚合查询 4 1 聚合查询举例 4 2 NULL值处理 五 分组查询 六 分页查询 七 INSERT INTO SE
  • ONES CTO

    2021年4月24日 4月26日 华为开发者大会在深圳大学城举办 本次大会主题为 每一个开发者都了不起 来自华为及各行业的技术大咖们与开发者汇聚一堂 探讨最新 ICT 技术在行业的深度创新与最佳实践 ONES CTO 冯斌先生受邀出席大会
  • 打开页面js自动加载的方法

    一 js方法 1 在body标签加onload属性 例 2 window onload方法 例 二 jQuery方法 1 window onload function alert 自动加载 2 document ready function
  • 全国计算机等级考试题库二级C操作题100套(第95套)

    第95套 给定程序中 函数fun的功能是 计算N N矩阵的主对角线元素和反向对角线元素之和 并作为函数值返回 注意 要求先累加主对角线元素中的值 然后累加反向对角线元素中的值 例如 若N 3 有下列矩阵 1 2 3 4 5 6 7 8 9
  • C++常量

    C 常量 常量是固定值 在程序执行期间不会改变 这些固定的值 又叫做字面量 常量可以是任何的基本数据类型 可分为整型数字 浮点数字 字符 字符串和布尔值 常量就像是常规的变量 只不过常量的值在定义后不能进行修改 整数常量 整数常量可以是十进
  • android webview 加载https

    在设置的WebViewClient 接收所有信任证书 wv setWebViewClient new WebViewClient Override public void onReceivedSslError WebView view Ss
  • 利用mysqldump实现分库分表备份的shell脚本

    一 信息摘要 linux版本 CentOS 7 9 mysql版本 MySQL 5 7 36 脚本实现功能 利用mysqldump工具实现对mysql中的数据库分库备份 和对所备份数据库中的表分表备份 二 shell脚本 bin bash
  • tensorflow的gpu版本错误

    出现错误 E tensorflow stream executor cuda cuda event cc 48 Error polling for event status failed to query event CUDA ERROR
  • statsmodels笔记:绘制ACF和PACF

    理论部分见 算法笔记 ARIMA UQI LIUWJ的博客 CSDN博客 3 1 3 2 1 绘制自相关函数ACF from statsmodels graphics tsaplots import plot acf plot acf df

随机推荐

  • Pytroch 模型权重初始化

    目录 1 概念 2 权值初始化方法 2 1 常数初始化 2 2 均匀分布初始化 2 3 正态分布初始化 2 4 Xavier 均匀分布 2 5 Xavier 正态分布 2 6 kaiming 均匀分布 2 7 kaiming 正态分布 2
  • 在产品中,我们常说的A端/B端/C端是什么?

    一 引言 在IT产品中 我们常常把各类型的技术系统分为A端 B端 C端 那它们到底是什么呢 又是有什么区别呢 今天小郭就带大家来仔细看看 二 我们常说的A端 B端 C端 R端是什么 2 1 产品分类 IT产品大致可以分为这四个类型 A端 是
  • 大数据数据仓库建设流程概述

    数据仓库的逻辑分层架构 想看懂数据仓库的逻辑分层架构 必须先弄懂以下4大概念 数据源 数据来源 互联网公司的数据来源随着公司的规模扩张而呈递增趋势 同时自不同的业务源 比如埋点采集 客户上报 API等 ODS层 数据仓库源头系统的数据表通常
  • html加载页面转圈圈怎么打,js实现等待加载“转圈圈”效果

    完美实现加载转圈圈效果 js代码 function showLoading show if show document getElementById over style display block document getElementB
  • MA35D1测试-记录

    1 查看拨码开关的启动设定 找到开发板 拨码快关 复位按键 电源开关的位置 2 三根线和软件 一根5V 2A电源适配线 两根usb线 三根线 一根5V 2A电源适配线 两根usb线 电源线插上 确保可以波动开关 有灯 点亮 usb线 在有电
  • 关键词提取(keyword extraction)技术

    目录 1 统计方法 Statistical Method 1 1 TF 1 2 TFIDF 1 3 YAKE 2 图方法 Graph Based Approaches 2 1 PageRank 2 2 TextRank 2 2 Single
  • easy-excel复杂格式

    1 支持easy excel模板与不同列表循环打印 合并表头 背景色 2 支持excel的高度自适应 3 支持多sheet页面模板打印 代码如下 Test public void compositeFill1 模板注意 用 来表示你要用的变
  • Docker 容器基础介绍

    目录 一 基础介绍 二 Docker 安装 linux 安装 vim linux 安装 sudo 三 Docker 常用操作命令 1 Docker windows版本安装 2 设置Docker镜像加速器 3 Docker 其它镜像相关 以D
  • 基因序列相似度(LCS)

    目录 1 问题描述 2 一些细节 3 思路 4 代码 1 问题描述 基因序列包含四种核苷酸 分别用A C T和G四个字母简单地表示 编写一个程序 按以下规则比较两个基因并确定它们的相似程度 规则 使用对齐方法 可以在基因的适当位置插进空格
  • [人工智能-深度学习-20]:卷积神经网络CNN - 全连接网络的缺点与CNN的使命

    作者主页 文火冰糖的硅基工坊 文火冰糖 王文兵 的博客 文火冰糖的硅基工坊 CSDN博客 本文网址 https blog csdn net HiWangWenBing article details 120732872 目录 第1章 全连接
  • Jlink使用技巧之RTT和J-Scope

    在调试单片机程序时 串口打印是一种非常常用的方式 有时候 硬件上没有预留串口时 就需要采用其它方式进行打印调试 1 Jlink SEGGER RTT Jlink SEGGER RTT是一种非常好用的方式 只需要通过Jlink的SWD或者JT
  • 前端面试题之CSS

    文章目录 遗留问题 1 css盒子模型 2 css选择器 3 伪类与伪元素的区别 回答 4 css中有哪些属性可以继承 5 CSS优先级 6 居中一个div 7 块级元素和行内元素的区别 8 position的值 9 CSS3 有哪些新特性
  • logminer介绍

    理解和使用Oracle 8i分析工具LogMiner Oracle LogMiner 是Oracle公司从产品8i以后提供的一个实际非常有用的分析工具 使用该工具可以轻松获得Oracle 重作日志文件 归档日志文件 中的具体内容 特别是 该
  • Windows下查看Android手机APP日志

    1 JDK环境搭建 略 在命令行窗口输入 java version 回车后显示版本号则表示JDK环境安装成功 2 配置adb环境 点击下方打开官网链 下载适用于Windows的SDK Platform Tools 下载成功后解压该文件 ht
  • 定时任务动态管理-Scheduled

    文章目录 前言 一 架构流程图 二 代码实现流程 1 引入库 2 代码流程 前言 定时任务动态管理分为两种方式 方式一 Web前台配置Trigger触发器 关联Cron ThreadPoolTaskScheduler类创建Scheduler
  • 蓝桥杯每日一题2023.9.21

    蓝桥杯2021年第十二届省赛真题 异或数列 C语言网 dotcpp com 题目描述 Alice 和 Bob 正在玩一个异或数列的游戏 初始时 Alice 和 Bob 分别有一个整数 a 和 b 有一个给定的长度为 n 的公共数列 X1 X
  • 与ajax类似的技术,介绍Ajax与jQuery技术

    Ajxs技术 异步的JavaScript与XML 已有多种技术的组合 Ajax的优点是什么 1 可以实现客户端的异步请求操作2 进而在不需要刷新页面的情况下与服务器进行通信 减少用户的等待时间3 减轻服务器和带宽的负担 提供更好的服务响应
  • linux socket bind 内核详解,Socket与系统调用深度分析(示例代码)

    1 什么是系统调用 操作系统通过系统调用为运行于其上的进程提供服务 当用户态进程发起一个系统调用 CPU 将切换到 内核态 并开始执行一个 内核函数 内核函数负责响应应用程序的要求 例如操作文件 进行网络通讯或者申请内存资源等 在Linux
  • 在 CentOS 上安装 Docker 引擎

    在 CentOS 上安装 Docker 引擎 预计阅读时间 11分钟 要在 CentOS 上开始使用 Docker 引擎 请确保 满足先决条件 然后 安装 Docker 先决条件 操作系统要求 要安装 Docker Engine 您需要 C
  • 双向广搜(bfs)

    双向广度优先搜索 广度优先搜索遵循从初始结点开始一层层扩展直到找到目标结点的搜索规则 它只能较好地解决状态不是太多的情况 承受力很有限 如果扩展结点较多 而目标结点又处在较深层 采用前文叙述的广度搜索解题 搜索量巨大是可想而知的 往往就会出