路径优化(基于python的DFS、BFS、A*算法的分析)

路径搜索问题

1. 创建一个随机的二维迷宫

得到一个二维迷宫,其中大小为10*20,起点是(0,0),终点是(19,19),生成障碍的概率是0.2,换而言之障碍的稀疏率为20%。(0表示为该坐标可以行进,x表示为障碍,S和G分别是起点个目标点。)在这里插入图片描述
根据上面这个迷宫,我们不难发现从S->G的路径有多条。那么怎么通过计算机程序去自己识别路径,是一个很有意思也很需要的,那么本文将介绍常见的三种路径搜索算法以供大家参考和共同学习。

2. DFS算法(深度优先搜索)

深度优先顾明思意,就是先顺着一个方向走到底(达到深度最大),然后没法走且还没到目标,那么就返回上一个决策点(决策点:有分叉路的点),然后选择另一条路走到底。这个深度优先搜索的思想很简单,再明白一点就是不拐弯,不决策,走不动再说。
以下图为例,起点是A0目标点是D2,其中的搜索路径是A0→B0→C1→D1然后深度达到了max,需要返回上一个决策点也就是B0,就从B0选另一条路走也就是B0→C2,同理B0这个点的所有决策的全深度都遍历过了,没法达到终点,那就继续返回上一个决策点。
在这里插入图片描述
根据这个解释和路径的搜索方式,相信大家都可以想到栈的用法,而使用DFS算法的时候调用栈的概念是可以大幅度降低编程难度的。
根据上面的迷宫得到下面的路径:在这里插入图片描述

3. BFS算法(广度优先搜索)

深度优先顾明思意,就是先广度搜索,也就是横着走,把所有点都走一遍。这样会导致大部分情况下都比DFS算得慢,但是BFS总会给我们得出一个最短的路径解。
在这里插入图片描述在这里插入图片描述

可以对比DFS可以看出之前的DFS采用的是栈,而实现BFS则是采用队列(queue)的数据结构。栈是LIFO(先进后出),而队列是FIFO(先进先出)。

3. A*算法

首先明确采用A算法的目的,由于BFS和DFS前者是可以求出最短路径,而DFS是可以在最快的方式下找到一条合适的路径。而A算法综合了两个的优点,利用距离的因素对每个取点进行一次加权的判断。对比BFS算法来说,同样是得到最短路径,但用时相对而言降低不少;对比DFS算法来说,可以在短时间内找到最优路径。取两者的长处已经摒弃短处。
A*算法是结合了代价函数g(n)和启发函数h(n),启发函数是对问题解决方式的一种直觉,目的是尽可能的寻求下一个最短路上的点,
采用的距离可以选择欧拉距离或曼哈顿距离:

def manhatan_disance(goal: MazeLocation) -> Callable[[MazeLocation], float]:  # 曼哈顿距离(横纵坐标差绝对值之和)
    def distance(ml: MazeLocation) -> float:
        xdist: int = abs(ml.column - goal.column)
        ydist: int = abs(ml.row - goal.row)
        return xdist + ydist
    return distance

在这里插入图片描述

4. 放大迷宫,对比各种算法求解迷宫问题的差别

在这里插入图片描述
可以看出:
BFS算法对比DFS算法来说可以得到更优的路线,但是运算时间较长,大概是DFS算法的一倍;
BFS算法对比采用曼哈顿距离的A算法来说,虽然路线长度一致,但A算法明显运算效率更高,大概只是BFS算法运行时间的20%;
DFS算法对比采用曼哈顿距离的A算法来说,虽然运算时间大致一样,但A算法可以得到更短的路线,而在现实长距离的问题中更具有实际意义;
A算法采用曼哈顿距离和采用欧拉距离虽然得到一样的路线,但是求解欧拉距离的时候运算量比曼哈顿距离多,使用时间接近7倍。
综上所述,求解迷宫问题,求解路径问题(二维),在该3种算法中,大概率还是使用A
(曼哈顿距离)算法最具好处。
最终程序(text.py)

from __future__ import annotations
from typing import TypeVar, Generic, List, Callable, Set, Optional, Deque, Dict
from heapq import heappush, heappop
T = TypeVar('T')


class Stack(Generic[T]):
    def __init__(self) -> None:
        self._container: List[T] = []

    @property
    def empty(self) -> bool:
        return not self._container

    def push(self, item: T) -> None:
        return self._container.append(item)

    def pop(self):
        return self._container.pop()

    def __repr__(self) -> str:
        return repr(self._container)


class Node(Generic[T]):
    def __init__(self, state: T, parent: Optional[Node], cost: float = 0, heuristic: float = 0) -> None:
        self.state: T = state
        self.parent: Optional[Node] = parent
        self.cost: float = cost
        self.heuristic = heuristic

    def __lt__(self, other):
        return (self.cost + self.heuristic) < (other.cost + other.heuristic)


def dfs(initial: T, goal_test: Callable[[T], bool], successors: Callable[[T], List[T]]) -> Optional[Node[T]]:
    frontier: Stack[Node[T]] = Stack()
    frontier.push(Node(initial, Node))
    explored: Set[T] = {
   initial}

    while not frontier.empty:
        current_node: Node[T] = frontier.pop()
        current_state: T = current_node.state
        if goal_test(current_state):
            return
  • 2
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python中,DFS深度优先搜索)和BFS广度优先搜索)可以通过使用列表和字典来实现。在DFS中,我们使用栈来保存遍历的节点,而在BFS中,我们使用队列来保存节点。下面是一些Python代码示例: 1. BFS的实现: ```python graph = { "A": ["B", "C"], "B": ["A", "C", "D"], "C": ["A", "B", "D", "E"], "D": ["B", "C", "E", "F"], "E": ["C", "D"], "F": ["D"] } def BFS(graph, s): queue = [] queue.append(s) seen = [] seen.append(s) while len(queue) > 0: vertex = queue.pop(0) nodes = graph[vertex] for node in nodes: if node not in seen: queue.append(node) seen.append(node) print(vertex) BFS(graph, "A") ``` 2. DFS的实现: ```python def DFS(graph, s): stack = [] stack.append(s) seen = [] seen.append(s) while len(stack) > 0: vertex = stack.pop() nodes = graph[vertex] for node in nodes: if node not in seen: stack.append(node) seen.append(node) print(vertex) DFS(graph, "A") ``` 对于BFS,我们还可以通过添加一个映射表(字典)来记录从起始点到其他所有点的路径。下面是一个对BFS的扩展,使用字典来记录父节点的信息,从而实现找到最短路径的功能: ```python def BFS(graph, s): queue = [] queue.append(s) seen = [] seen.append(s) parent = {s: None} while len(queue) > 0: vertex = queue.pop(0) nodes = graph[vertex] for node in nodes: if node not in seen: queue.append(node) seen.append(node) parent[node = vertex print(vertex) return parent parent = BFS(graph, "A") v = "E" while v != None: print(v) v = parent[v] ``` 希望这些代码能够帮助你理解Python中的DFSBFS算法。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Python BFSDFS算法](https://blog.csdn.net/qq_43540763/article/details/115144191)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值