路径规划——广度优先搜索与深度优先搜索

news2024/9/19 9:27:12

路径规划——广度优先搜索与深度优先搜索

https://www.hello-algo.com/chapter_graph/graph_traversal/

1.广度优先搜索 Breath-First-Search

在图论中也称为广度优先遍历,类似于树的层序遍历。

算法原理

从起始节点出发,首先访问它的邻近节点,然后依次访问这些邻近节点的邻近节点,直到所有节点都被访问到。广度优先搜索是从一个起始节点开始逐层地访问所有节点的。

广度优先搜索是一种图遍历算法,每向前走一步可能访问一批顶点,不像深度优先搜索那样有回退的情况,因此它不是一个递归的算法。为了实现逐层的访问,算法必须借助一个辅助队列,以记忆正在访问的顶点的下一层顶点。

现有如下节点图Graph,要求从A点开始搜索,搜索全部节点,将节点搜索序列作为结果输出。
在这里插入图片描述

将上图整理得下图
在这里插入图片描述

那么整个广度优先搜索的过程如下图:
在这里插入图片描述

算法实现

from collections import deque

def bfs(graph, start):
    # 初始化队列,并将起始节点加入队列
    queue = deque([start])
    # 初始化访问顺序列表
    visited = [start]

    while queue:
        # 取出队列中的当前节点
        current = queue.popleft()
        
        # 遍历当前节点的所有邻居节点
        for neighbor in graph[current]:
            if neighbor not in visited:  # 如果邻居节点尚未被访问
                # 将邻居节点加入队列
                queue.append(neighbor)
                # 记录访问顺序
                visited.append(neighbor)

    return visited

# 示例图的定义
graph = {
    'A': ['B', 'C'],
    'B': ['A', 'D', 'E'],
    'C': ['A', 'F'],
    'D': ['B'],
    'E': ['B', 'F'],
    'F': ['C', 'E']
}

# 使用BFS算法
start_node = 'A'
visited = bfs(graph, start_node)
print(f"Visit order: {visited}")

寻找在上图中A->E的最短路径:

from collections import deque

def bfs(graph, start, goal):
    # 初始化队列,并将起始节点加入队列
    queue = deque([start])
    # 初始化访问顺序列表
    visited = [start]
    # 初始化父节点集合
    previous = {start: None}

    while queue:
        # 取出队列中的当前节点
        current = queue.popleft()

        if current == goal:
            break
        
        # 遍历当前节点的所有邻居节点
        for neighbor in graph[current]:
            if neighbor not in visited:  # 如果邻居节点尚未被访问
                # 将邻居节点加入队列
                queue.append(neighbor)
                # 记录访问顺序
                visited.append(neighbor)
                # 将当前节点保存为邻节点的父节点
                previous[neighbor] = current

    path = []
    current = goal
    # Find the full path by backtracking
    while current is not None:
        path.append(current)
        current = previous.get(current)
    path = path[::-1]
    distance = len(path)-1

    return path,distance

# 示例图的定义
graph = {
    'A': ['B', 'C'],
    'B': ['A', 'D', 'E'],
    'C': ['A', 'F'],
    'D': ['B'],
    'E': ['B', 'F'],
    'F': ['C', 'E']
}

# 使用BFS算法
start = 'A'
goal = 'E'
path,distance = bfs(graph, start, goal)
print("Distance: ",distance)
print(f"Short path: {path}")

输出结果:
在这里插入图片描述

利用BFS算法寻找栅格地图中两点之间的最短路径的代码实现如下:


from collections import deque
import numpy as np

class BFS:
    def __init__(self, grid, board_size, start, goal):
        self.grid = grid
        self.board_size = board_size
        self.start = start
        self.goal = goal

    def plan(self):
        """
            Use BFS algorithm to plan path in grid map.
            Since the cost between every two neighbouring nodes is 1 which is different from Dijkstra,
            only four directions including up, right, down, left are allowed
        
        """

        visited = set() # Used to mark nodes that are visited
        self.searched = [] # Used to record nodes that are searched

        previous_nodes = {self.start: None}

        que = deque([self.start])

        visited.add(self.start)

        while que:
            # Select the node closest to the start node
            current_node = que.popleft()

            # Append the current node into searched nodes
            self.searched.append(current_node)
            
            # Break when the current node is the goal
            if current_node == self.goal:
                break
            
            # Find the neighbors of the current node and determine in turn if they have already been visited
            neighbors = self.get_neighbors(current_node)
            for neighbor in neighbors:
                # If the current node has been visited, skip it
                if neighbor in visited:
                    continue

                previous_nodes[neighbor] = current_node
                que.append(neighbor)
                visited.add(neighbor) # mark the neighbor is visited
        
        self.path = []
        current_node = self.goal
        # Find the full path by backtracking
        while current_node is not None:
            self.path.append(current_node)
            current_node = previous_nodes.get(current_node)
        self.path = self.path[::-1]

        return len(self.path)-1


    def get_neighbors(self, node):
        neighbors = []
        next_directions = [(1,0),(0,-1),(-1,0),(0,1)]

        for next_d in next_directions:
            neighbor = (node[0] + next_d[0], node[1] + next_d[1])
            if self.board_size <= neighbor[0] < len(self.grid)-self.board_size and self.board_size <= neighbor[1] < len(self.grid[0])-self.board_size:
                if self.grid[neighbor[0]][neighbor[1]] == 0:
                    neighbors.append(neighbor)

        return neighbors

在这里插入图片描述

2.深度优先搜索 Depth-First-Search

在树和图论的数据结构中也称为深度优先遍历。

算法原理

从起始节点出发,沿着一个分支深入到尽可能深的节点,然后回溯并继续访问其他分支。这种"走到尽头再返回"的算法范式通常是基于递归来实现的。

同样以上述例子为例,整个深度优先搜索的过程如下:

在这里插入图片描述

算法实现

from collections import deque

def dfs(graph, current_node, visited):

    visited.append(current_node)
    
    # 遍历当前节点的所有邻居节点
    for neighbor in graph[current_node]:
        if neighbor in visited:  # 如果邻居节点已被访问则跳过
            continue
        dfs(graph, neighbor, visited)

    return visited

# 示例图的定义
graph = {
    'A': ['B', 'C'],
    'B': ['A', 'D', 'E'],
    'C': ['A', 'F'],
    'D': ['B'],
    'E': ['B', 'F'],
    'F': ['C', 'E']
}

# 使用DFS算法
start_node = 'A'
visited = dfs(graph, start_node, [])
print(f"Visit order: {visited}")

寻找在上图中A->E的最短路径:

from collections import deque

def dfs(graph, current_node, goal, path, shortest_path, distance):

    path.append(current_node)
    
    if current_node == goal:
        if len(path)-1<distance:
            shortest_path[:] = path
            distance = len(shortest_path)-1
        path.pop()
        return shortest_path, distance
    
    # 遍历当前节点的所有邻居节点
    for neighbor in graph[current_node]:
        if neighbor in path:  # 如果邻居节点已被访问则跳过
            continue

        shortest_path, distance = dfs(graph, neighbor, goal, path, shortest_path, distance)
    
    path.pop()

    return shortest_path, distance


# 示例图的定义
graph = {
    'A': ['B', 'C'],
    'B': ['A', 'D', 'E'],
    'C': ['A', 'F'],
    'D': ['B'],
    'E': ['B', 'F'],
    'F': ['C', 'E']
}

# 使用DFS算法
start_node = 'A'
goal = 'F'
path = []
distance = float('inf')
shortest_path, distance = dfs(graph, start_node, goal, path, [], distance)
print("Distance: ",distance)
print(f"Short path: {shortest_path}")

输出结果:

在这里插入图片描述

虽然DFS可以找到最短路径,但是需要找到所有的路径之后才能知道最短路径,所有非常耗时,例如在上述BFS中的栅格地图中寻找起点到终点的最短路径是非常困难的,尽管也可以找到最短路径但是非常耗时,所以一般不会使用DFS寻找最短路径。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

openEuler中安装数据库

目录 一.安装数据库 二.出现报错解决方法 1.根据报错查看冲突软件包 2.忽略软件依赖性解决 3.再次查看是否删掉冲突软件 三.再次执行安装数据库命令 四.启动数据库可直接输入mysql进入数据库&#xff0c;此时不安全 五.安全初始化 1.是否有root密码&#xff0c;没有直…

从表型感知到全链路贯通:数字孪生与LLM重塑设施农业新范式

当前,设施农业正处于从传统模式向现代智慧农业加速跃迁的关键时期。数字孪生和大语言模型引领的技术变革浪潮为催生设施农业的创新发展模式提供了新的可能。二者携手打造的全场景数字化运营新范式,必将重塑农业生产的业态和价值链。农业科技工作者应顺应时代发展潮流,将数字孪生…

iOS-Swift 数据库 WCDB 二次封装使用/自定义字段映射类型

WCDB官方使用文档 WCDB简介 WCDB 是一个易用、高效、完整的移动数据库框架&#xff0c;它基于 SQLite 和 SQLCipher 开发&#xff0c;在微信中应用广泛&#xff0c;且支持在 C、Java、Kotlin、Swift、Objc 五种语言环境中使用。 整体架构&#xff1a; 对于WCDB详细的介绍和…

Tomcat安装教程

Tomcat官方网站&#xff1a;http://tomcat.apache.org/ 1.找到左边一栏有个Download&#xff0c;点击Tomcat 10 注意&#xff1a;Tomcat也是要下载JDK环境的&#xff0c;这里我使用Tomcat 10&#xff0c;JDK环境要大于等于11版本&#xff0c;具体可看下图&#xff1a; 2.下拉找…

更小、更安全、更透明:Google发布的Gemma推动负责任AI的进步

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

Python习题 101:输入年月打印日历

使用了 Python 的内置库 calendar&#xff0c;它提供提供与日历有关功能&#xff0c;可以帮助我们做时间日期相关的计算&#xff0c;省去复杂的判断&#xff0c;比较实用。

cv2读取中文路径图像名称

1.cv2.imdecode 是 OpenCV 库中的一个函数&#xff0c;用于从内存中的数据解码图像。这通常用于从文件、网络传输或数据库中读取图像数据而不必直接从磁盘读取。此函数特别适用于处理字节数组形式的图像数据。 img cv2.imdecode(buf, flagsNone) 参数说明&#xff1a; buf&am…

解锁PDF编辑新境界:2024年大家都在用的4款工具

PDF这个文件格式大家应该都不陌生吧。他以不易窜改和可以保持版式一直的优势成为我们日常传输文件的首选格式。随着使用使用率的增加&#xff0c;一些PDF表格如果能直接修改内容就能有效的提升工作效率。这就需要借助一些PDF编辑工具来实现啦。 1.福昕PDF编辑器 直达链接&am…

游戏(河南萌新2024)

1.超时的写法&#xff08;没有用堆优化&#xff09; #include <bits/stdc.h>using namespace std; typedef long long ll; typedef double db; typedef long double ldb; typedef pair<int, int> pii; typedef pair<ll, ll> PII; #define pb emplace_back /…

vulnhub靶场serial-php渗透(蜥蜴细!)

目录 一、信息收集 1.探测主机存活&#xff08;目标主机IP地址&#xff09; 2.访问web服务 3.后台目录和端口扫描 4.解析bak.zip源码 二、漏洞利用 1.构造payload 2.通过bp的repeater模块 3.get shell 4.获取反弹shell 三、提升权限 1. 查看系统版本&#xff0c;内核…

ctfshow 大赛原题 web697--web700

web697 先扫一下&#xff0c;其实也可以不用扫 因为什么也扫不出来 这里看到有一个参数 尝试一下数组 随便输了&#xff0c;出了验证回显抓个包看 ffifdyop e58 4611686052576742364这三个md5加密可以自带引号 SELECT master FROM secret WHERE password binary ,b…

文件包含漏洞汇总

文章目录 原理文件包含函数伪协议函数本地包含file协议filter协议input协议data协议 远程文件包含条件http协议 日志文件绕过概念日志路径复现 文件包含之条件竞争概念靶场介绍复现 文件下载文件下载常见的目录系统目录linuxwindows 程序配置文件apachenginxredis 目录遍历与目…

【STL专题】深入探索vector:动态数组的魔力【入门指南】

欢迎来到 CILMY23 的博客 &#x1f3c6;本篇主题为&#xff1a;深入探索vector&#xff1a;动态数组的魔力&#xff0c;入门指南 &#x1f3c6;个人主页&#xff1a;CILMY23-CSDN博客 &#x1f3c6;系列专栏&#xff1a;Python | C | C语言 | 数据结构与算法 | 贪心算法 | L…

结构体指针数组函数综合应用改写选票系统

第一次写百行的代码 有点吃不消 感受到程序员的不容易 其中遇到了很多问题 希望分享给大家 下面是是完整的且完善的代码 #include<stdio.h> #include<string.h> #include <stdlib.h> //定义结构体 struct XuanMin {char name[32];int tickets; }; //指针函…

1-4章节复习总结

1-4章节总结 章节重点回顾-第一章-中央处理单元练习题 章节重点回顾-第一章-进制章节重点回顾-第一章-校验码奇偶校验码CRC循环冗余校验码海明码练习题 多草节重点回顾-第一草-计算机体系结构分类章节重点回顾-第一章-计算机指令练习题 章节重点回顾-第一章-指令流水线练习题 章…

​​​​​Tomcat部署及优化

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…

洞见新能源汽车产业更智能的未来

新能源汽车行业进入智能化时代&#xff0c;除了备受关注的无人驾驶领域&#xff0c;新能源汽车在智能化的进程逐渐加快。智能化已成为中国汽车品牌的竞争力。 作为专业提供算网的服务商之一&#xff0c;VERYCLOUD睿鸿股份跟随新能源汽车行业快速变化&#xff0c;受邀前往CIAS 2…

天环公益首次推出原创开发进度网站,配备后台管理系统

天环公益组织近期创新性地发布了一个专用于监控与展示项目开发进程的官方网站&#xff0c;该网站特色在于其自研的后台管理系统。 对于有兴趣深入了解或参与管理的用户&#xff0c;可直接访问后台页面&#xff0c;入口为&#xff1a;admin.php。 值得注意的是&#xff0c;当前…