(8-5)优先级遍历(Priority-based Search)算法:广度优先搜索(Breadth First Search)算法

8.5  广度优先搜索(Breadth First Search)算法

广度优先搜索(Breadth First Search,BFS)是一种用于图的遍历或搜索的算法。与深度优先搜索不同,广度优先搜索从起始节点开始,逐层地向外扩展,先访问起始节点的所有相邻节点,然后是这些相邻节点的相邻节点,依此类推,直到到达目标节点或遍历完所有节点。

8.5.1  广度优先搜索算法介绍

广度优先搜索(Breadth First Search,BFS)的基本思想是从起始节点开始,逐层地向外扩展搜索,直到找到目标节点或者遍历完所有可达节点。其核心思想包括如下所示的关键步骤:

(1)从起始节点开始:*BFS算法从一个起始节点开始,将其放入一个队列中,作为待访问的节点之一。

(2)逐层扩展:在每一轮搜索中,BFS先访问当前层级的所有节点,然后再访问下一层级的所有节点。这保证了先访问离起始节点近的节点,然后逐层向外扩展。

(3)标记已访问节点:在访问一个节点时将其标记为已访问,以避免重复访问。这样可以通过设置一个布尔数组或哈希集来实现。

(4)使用队列实现:BFS通常使用队列数据结构来实现,它遵循先进先出(FIFO)的原则,保证了在同一层级的节点都会在探索下一层级节点之前被访问。

(5)终止条件:BFS会一直执行直到队列为空或者找到目标节点为止,如果找到了目标节点,算法会立即终止,并返回相应的结果。

总的来说,BFS算法通过逐层扩展搜索的方式,保证了从起始节点到目标节点的路径是最短的,因此常用于寻找最短路径或者搜索图中的连通性。下面是广度优先搜索算法的伪代码表示:

BFS(G, start):
    queue Q := empty queue
    visited := set()
    Q.enqueue(start)
    visited.add(start)
    
    while Q is not empty:
        current := Q.dequeue()
        process(current)
        
        for neighbor in neighbors(current):
            if neighbor is not in visited:
                Q.enqueue(neighbor)
                visited.add(neighbor)
```

在上述伪代码中,BFS是广度优先搜索算法的主要函数,它接受一个图 G和一个起始节点 start作为参数。首先创建一个空队列 Q和一个空的集合 visited用于记录已经访问过的节点。然后将起始节点 start放入队列中,并将其标记为已访问。接着执行一个循环,直到队列为空。在循环中,从队列中取出一个节点 current并对其进行处理,然后遍历 current节点的所有相邻节点 neighbor,如果某个相邻节点尚未被访问过,则将其放入队列中并标记为已访问。

8.5.2  广度优先搜索算法介绍

请看下面的例子,功能是在一个迷宫中寻找一条从起点到终点的最短路径。假设迷宫是一个由0和1组成的二维矩阵,其中0表示可通行的空格,1表示墙壁阻挡。机器人只能水平或垂直移动,不能斜向移动,并且它不能穿过墙壁。我们将使用广度优先搜索算法来解决这个问题。

实例8-6使用广度优先搜索算法为机器人寻找最短路径codes/8/bbfs.py

实例文件bbfs.py的具体实现代码如下所示。

from collections import deque
import matplotlib.pyplot as plt

def is_valid_move(maze, row, col, visited):
    rows = len(maze)
    cols = len(maze[0])
    return row >= 0 and row < rows and col >= 0 and col < cols and maze[row][col] == 0 and not visited[row][col]

def bfs_shortest_path(maze, start, end):
    if start == end:
        return [start]
    
    rows = len(maze)
    cols = len(maze[0])
    directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]  # 右、下、左、上
    
    queue = deque()
    queue.append([start])
    visited = [[False for _ in range(cols)] for _ in range(rows)]
    visited[start[0]][start[1]] = True
    
    while queue:
        path = queue.popleft()
        current_row, current_col = path[-1]
        for dr, dc in directions:
            new_row = current_row + dr
            new_col = current_col + dc
            if is_valid_move(maze, new_row, new_col, visited):
                visited[new_row][new_col] = True
                new_path = list(path)
                new_path.append((new_row, new_col))
                queue.append(new_path)
                if (new_row, new_col) == end:
                    return new_path

def plot_maze_with_path(maze, shortest_path):
    rows = len(maze)
    cols = len(maze[0])

    plt.figure(figsize=(cols, rows))
    plt.imshow(maze, cmap='binary')

    for row, col in shortest_path:
        plt.text(col, row, 'X', ha='center', va='center', color='red')

    for i in range(len(shortest_path) - 1):
        current_row, current_col = shortest_path[i]
        next_row, next_col = shortest_path[i+1]
        plt.plot([current_col, next_col], [current_row, next_row], color='blue', linewidth=2)

    plt.xticks(range(cols))
    plt.yticks(range(rows))
    plt.gca().invert_yaxis()  # 反转y轴,使得坐标原点在左上角
    plt.grid(color='gray', linestyle='--', linewidth=0.5)
    plt.title('Maze with Shortest Path')
    plt.show()

# 示例迷宫
maze = [
    [0, 1, 0, 0, 0],
    [0, 0, 0, 1, 0],
    [1, 1, 0, 1, 0],
    [1, 1, 0, 0, 0],
    [1, 1, 1, 1, 0]
]

start = (0, 0)
end = (4, 4)
shortest_path = bfs_shortest_path(maze, start, end)

if shortest_path:
    print("Shortest path found:")
    for row, col in shortest_path:
        print(f"({row}, {col}) -> ", end="")
    print("Destination")
    
    plot_maze_with_path(maze, shortest_path)
else:
    print("No path found!")

上述代码的实现流程如下所示:

(1)首先,定义了一个迷宫,迷宫是一个由0和1组成的二维矩阵,其中0表示可通行的空格,1表示墙壁阻挡。迷宫中有一个起始点和一个终点。

(2)然后,使用广度优先搜索算法(BFS)来寻找从起始点到终点的最短路径。在 bfs_shortest_path 函数中,使用队列来实现BFS算法。我们从起始点开始,将其放入队列中,并标记为已访问。然后,我们不断地从队列中取出节点,并探索其相邻节点。如果某个相邻节点尚未被访问过,我们将其添加到队列中,并继续探索。当我们找到终点时,就结束搜索。

(3)接着,定义了一个 plot_maze_with_path 函数来绘制迷宫和最短路径。使用 imshow 函数绘制迷宫,然后在起始点和终点上标记出红色的标记。此外,我们使用 plot 函数在找到的最短路径上绘制蓝色的线条,以表示机器人应该行走的路线。

(4)最后,主程序中调用 bfs_shortest_path 函数来找到最短路径,并使用 plot_maze_with_path 函数将迷宫和路径绘制出来。这样,就完成了寻找最短路径并可视化的任务。

执行后会打印输出如下所示的路径信息,并绘制如图8-5所示的路径可视化图。

Shortest path found:
(0, 0) -> (1, 0) -> (1, 1) -> (1, 2) -> (2, 2) -> (3, 2) -> (3, 3) -> (3, 4) -> (4, 4) -> Destination

图8-5  路径可视化图

  • 18
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农三叔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值