博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
算法(三):图解广度优先搜索算法
阅读量:6221 次
发布时间:2019-06-21

本文共 3020 字,大约阅读时间需要 10 分钟。

算法简介

广度优先搜索算法(Breadth First Search),又称为"宽度优先搜索"或"横向优先搜索",简称BFS; BFS是用于的查找算法(要求能用图表示出问题的关联性)。

BFS可用于解决2类问题:

  • 从A出发是否存在到达B的路径;
  • 从A出发到达B的最短路径(这个应该叫最少步骤合理);

其思路为从图上一个节点出发,访问先访问其直接相连的子节点,若子节点不符合,再问其子节点的子节点,按级别顺序依次访问,直到访问到目标节点。

所谓的"图"为:

案例

如上图所示,找出从A到H的最短路径(步骤最少的,假设每一段距离相等),此时就可以使用广域搜索算法,原理步骤为:

  1. 假设存在一个空的搜索队列Queue,首先将节点A添加进队列Queue
  2. 判断队列第一个节点是否是需要查找的目标节点,若不是,则将第一个节点的直接子节点添加进队列,并移除第一个节点
  3. 重复判断,直到第一个节点为目标节点,或者队列为空(即代表没有合适的)

如下图所示:

过滤已经搜索过的节点

对于已经搜索过的节点,最好将其唯一的id标识保存下来,后续搜索过程中如果再次出现该节点则跳过不再重复搜索,以提高效率和避免死循环;

java实现

public class BFS {        	public static void main(String[] args){    		//初始化先建立起各个节点信息,以及对应的直接子节点列表    		HashMap
map = new HashMap<>(); map.put("A", new String[] {
"B","C"}); map.put("B", new String[] {
"E"}); map.put("C", new String[] {
"D","F"}); map.put("D", new String[] {
"E"}); map.put("E", new String[] {
"H"}); map.put("F", new String[] {
"E","G"}); map.put("G", new String[] {
"H"}); map.put("H", new String[] {}); //获取从A到H的最短路径节点链表 Node target = findTarget("A","H",map); //打印出最短路径的各个节点信息 printSearPath(target); } /** * 打印出到达节点target所经过的各个节点信息 * @param target */ static void printSearPath(Node target) { if (target != null) { System.out.print("找到了目标节点:" + target.id + "\n"); List
searchPath = new ArrayList
(); searchPath.add(target); Node node = target.parent; while(node!=null) { searchPath.add(node); node = node.parent; } String path = ""; for(int i=searchPath.size()-1;i>=0;i--) { path += searchPath.get(i).id; if(i!=0) { path += "-->"; } } System.out.print("步数最短:"+path); } else { System.out.print("未找到了目标节点"); } } /** * 从指定的开始节点 startId ,查询到目标节点targetId 的最短路径 * @param startId * @param targetId * @param map * @return */ static Node findTarget(String startId,String targetId,HashMap
map) { List
hasSearchList = new ArrayList
(); LinkedList
queue = new LinkedList
(); queue.offer(new Node(startId,null)); while(!queue.isEmpty()) { Node node = queue.poll(); if(hasSearchList.contains(node.id)) { //跳过已经搜索过的,避免重复或者死循环 continue; } System.out.print("判断节点:" + node.id +"\n"); if (targetId.equals(node.id)) { return node; } hasSearchList.add(node.id); if (map.get(node.id) != null && map.get(node.id).length > 0) { for (String childId : map.get(node.id)) { queue.offer(new Node(childId,node)); } } } return null; } /** * 节点对象 * @author Administrator * */ static class Node{ //节点唯一id public String id; //该节点的直接父节点 public Node parent; //该节点的直接子节点 public List
childs = new ArrayList
(); public Node(String id,Node parent) { this.id = id; this.parent = parent; } } }复制代码

执行完main方法打印信息如下:

判断节点:A    判断节点:B    判断节点:C    判断节点:E    判断节点:D    判断节点:F    判断节点:H    找到了目标节点:H    步数最短:A-->B-->E-->H复制代码

扫描关注微信公众号:

转载地址:http://qerja.baihongyu.com/

你可能感兴趣的文章
7道常见的数据分析面试题
查看>>
Go语言很好很强大,但我有几个问题想吐槽
查看>>
工作的未来:敏捷人士瑞典大会上午议程回顾
查看>>
“认知计算”如何有效释放数据价值
查看>>
采访与书评 —— 《BDD In Action》
查看>>
Java永久代去哪儿了
查看>>
解读:Java 11中的模块感知服务加载器
查看>>
微软为无服务器架构引入新API管理消费层
查看>>
《Clojure Recipes》书评与问答
查看>>
微服务通信策略
查看>>
Apache Pulsar中的地域复制,第1篇:概念和功能
查看>>
实现一个最简单的模板分离
查看>>
Java的序列化特性将要退出历史舞台了
查看>>
SQLer:无需编程语言即可将SQL查询转换为RESTful API的工具
查看>>
Phantom.js维护者退出,项目的未来成疑
查看>>
京东物流王梓晨:打造全栈团队,你要避开这些大坑
查看>>
解决C# 7.2中的结构体性能问题
查看>>
2018年最好的45个Vue开源项目汇总
查看>>
Oracle即将发布的全新Java垃圾收集器 ZGC
查看>>
微软发布Azure Time Series Insight正式版
查看>>