【Python搜索算法】广度优先搜索(BFS)算法原理详解与应用,示例+代码

news2024/11/21 1:25:28

目录

1 广度优先搜索    

2 应用示例

2.1 迷宫路径搜索

2.2 社交网络中的关系度排序

2.3 查找连通区域


1 广度优先搜索    

        广度优先搜索(Breadth-First Search,BFS)是一种图遍历算法,用于系统地遍历或搜索图(或树)中的所有节点。BFS的核心思想是从起始节点开始,首先访问其所有相邻节点,然后逐层向外扩展,逐一访问相邻节点的相邻节点,以此类推。这意味着BFS会优先探索距离起始节点最近的节点,然后再逐渐扩展到距离更远的节点。BFS通常用于查找最短路径、解决迷宫问题、检测图是否连通以及广泛的图问题。

BFS算法的步骤如下:

  1. 初始化:选择一个起始节点,将其标记为已访问,并将其放入队列中(作为起始节点)。

  2. 进入循环:重复以下步骤,直到队列为空。 a. 从队列中取出一个节点。 b. 访问该节点。 c. 将所有未访问的相邻节点加入队列。 d. 标记已访问的节点,以避免重复访问。

  3. 结束循环:当队列为空时,表示已经遍历完整个图。

以下是BFS的算法原理详解和一个应用示例:

算法原理:

        BFS的工作原理是通过队列数据结构来管理待访问的节点。它从起始节点开始,然后逐一访问该节点的相邻节点,并将它们加入队列。然后,它从队列中取出下一个节点进行访问,以此类推。这确保了节点按照它们的距离从起始节点逐层遍历,因此BFS可以用于查找最短路径。

        BFS是一个宽度优先的搜索,它在查找最短路径等问题中非常有用。它不会陷入深度过深的路径,因为它会优先探索距离起始节点更近的节点。

2 应用示例

2.1 迷宫路径搜索

        假设有一个迷宫,其中包含墙壁和通道,您希望找到从起始点到终点的最短路径。BFS是解决这类问题的理想选择。

示例迷宫:

S 0 0 1 1 1
1 1 0 1 0 1
1 0 0 0 0 1
1 1 1 1 0 1
1 0 0 1 0 1
1 1 1 1 1 E
  • S 表示起始点
  • E 表示终点
  • 0 表示可以通过的通道
  • 1 表示墙壁

 使用BFS,您可以找到从起始点到终点的最短路径,如下所示:

  1. 从起始点 S 开始,将其加入队列。
  2. 逐层遍历节点,首先访问距离 S 最近的节点。
  3. 在每一步中,将所有可以通过的相邻节点加入队列,同时标记已访问的节点。
  4. 继续这个过程,直到到达终点 E

BFS会优先探索距离 S 最近的通道,因此它会找到从 SE 的最短路径。在上面的迷宫中,BFS将找到一条最短路径,经过标有数字 0 的通道,最终到达终点 E。这是BFS在寻找最短路径问题中的一个实际应用示例。

示例:

import matplotlib.pyplot as plt
from collections import deque


def bfs_shortest_path(maze, start, end):
    # 定义四个方向移动的偏移量,分别是上、下、左、右
    directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
    rows, cols = len(maze), len(maze[0])

    # 创建队列用于BFS
    queue = deque([(start, [start])])
    visited = set()

    while queue:
        (x, y), path = queue.popleft()
        visited.add((x, y))

        if (x, y) == end:
            return path  # 找到了最短路径

        for dx, dy in directions:
            new_x, new_y = x + dx, y + dy

            if 0 <= new_x < rows and 0 <= new_y < cols and maze[new_x][new_y] == 0 and (new_x, new_y) not in visited:
                new_path = path + [(new_x, new_y)]
                queue.append(((new_x, new_y), new_path))

    return None  # 没有找到路径

def draw_maze(maze, path=None):
    rows, cols = len(maze), len(maze[0])

    # 创建一个图形对象
    fig, ax = plt.subplots()

    # 绘制迷宫
    for x in range(rows):
        for y in range(cols):
            if maze[x][y] == 0:
                ax.add_patch(plt.Rectangle((y, -x - 1), 1, 1, facecolor="white"))
            else:
                ax.add_patch(plt.Rectangle((y, -x - 1), 1, 1, facecolor="gray"))

    # 绘制路径(如果存在)
    if path:
        for x, y in path:
            ax.add_patch(plt.Rectangle((y, -x - 1), 1, 1, facecolor="green"))

    # 设置坐标轴
    ax.set_aspect("equal")
    ax.set_xticks(range(cols))
    ax.set_yticks(range(-rows, 0))
    ax.set_xticklabels([])
    ax.set_yticklabels([])

    plt.grid(True)
    plt.show()


# 示例迷宫,0表示通道,1表示墙壁
maze = [
    [0, 0, 0, 1, 1, 1],
    [1, 1, 0, 1, 0, 1],
    [1, 0, 0, 0, 0, 1],
    [1, 1, 1, 1, 0, 1],
    [1, 0, 0, 1, 0, 0],
    [1, 1, 0, 0, 1, 0]
]

start = (0, 0)  # 起始点
end = (5, 5)  # 终点

path = bfs_shortest_path(maze, start, end)

draw_maze(maze, path)

2.2 社交网络中的关系度排序

        广度优先搜索(BFS)的排序应用示例之一是使用它在无权图中查找最短路径。在前面的示例中,我们已经展示了如何使用BFS查找迷宫中的最短路径。这是BFS的一个典型应用示例。

        另一个排序应用示例是社交网络中的关系度排序。在社交网络中,您可以使用BFS来确定您与其他用户之间的关系度,即您与其他用户之间的最短路径,或者共同的朋友数量。以下是一个简单的示例:

        假设您有一个社交网络,其中用户之间的关系用图表示,其中节点代表用户,边代表用户之间的关系。您想知道您与其他用户之间的关系度,并按关系度对用户进行排序。

import networkx as nx
import matplotlib.pyplot as plt
from collections import deque

# 创建一个复杂的社交网络图
social_network = {
    'You': ['Alice', 'Bob', 'Claire', 'David'],
    'Alice': ['Diana', 'Eva', 'Frank'],
    'Bob': ['Eva', 'Frank', 'George'],
    'Claire': ['Diana', 'George', 'Hannah'],
    'David': ['Hannah'],
    'Diana': ['Eva', 'George'],
    'Eva': ['Frank'],
    'Frank': ['George', 'Hannah'],
    'George': ['Hannah'],
    'Hannah': [],
}

def bfs_relationship_degree(graph, start):
    visited = set()
    queue = deque([(start, 0)])  # 用于存储节点和关系度

    relationship_degree = {}  # 存储关系度

    while queue:
        node, degree = queue.popleft()

        if node not in visited:
            visited.add(node)
            relationship_degree[node] = degree

            for friend in graph[node]:
                if friend not in visited:
                    queue.append((friend, degree + 1))

    return relationship_degree

# 使用BFS查找关系度
your_name = 'You'
relationship_degree = bfs_relationship_degree(social_network, your_name)

# 创建一个有向图
G = nx.DiGraph()

# 添加节点和边
for user, degree in relationship_degree.items():
    G.add_node(user, degree=degree)

for user in social_network:
    for friend in social_network[user]:
        G.add_edge(user, friend)

# 绘制图形
pos = nx.spring_layout(G, seed=42)
labels = nx.get_node_attributes(G, 'degree')
nx.draw(G, pos, with_labels=True, node_size=1000, node_color='lightblue', font_size=10, font_color='black')
nx.draw_networkx_labels(G, pos, labels, font_size=10, font_color='black')
plt.title("复杂社交网络图")
plt.show()

# 输出排序结果
sorted_users = sorted(relationship_degree.items(), key=lambda x: x[1])
for user, degree in sorted_users:
    print(f'{user}: 关系度 {degree}')

输出:

 输出:

You: 关系度 0
Alice: 关系度 1
Bob: 关系度 1
Claire: 关系度 1
David: 关系度 1
Diana: 关系度 2
Eva: 关系度 2
Frank: 关系度 2
George: 关系度 2
Hannah: 关系度 2

 这段代码的目的是使用广度优先搜索(BFS)算法来查找社交网络中您('You')与其他用户之间的关系度,并绘制社交网络图。

  1. 首先,定义了一个复杂的社交网络图,其中包括不同用户之间的关系。这个社交网络图存储在 social_network 字典中。

  2. bfs_relationship_degree 函数实现了BFS算法来查找您与其他用户之间的关系度。它从您开始,逐层查找与您相连接的用户,计算它们之间的关系度。结果存储在 relationship_degree 字典中。

  3. 创建一个有向图(DiGraph) G 以绘制社交网络图。

  4. 添加节点和边到图 G,其中节点代表用户,边代表用户之间的关系。此时,节点的颜色和大小被设置为 lightblue1000,并且边的颜色为 gray

  5. 使用 NetworkX 提供的布局算法 spring_layout 来确定节点的位置。

  6. 绘制图形,包括节点和边,以及节点上的标签。

  7. 输出用户的关系度排序结果,按照从您('You')到其他用户的关系度进行排序。

运行该代码将绘制出社交网络图,并输出用户的关系度排序结果。这可以帮助您可视化您与其他用户之间的关系,并查看谁与您更亲近。

2.3 查找连通区域

        在图像处理中,连通区域是由相邻像素组成的区域,具有相似的特性(如颜色或灰度)。BFS可以用来查找和标记这些连通区域。

import cv2
import numpy as np

# 读取图像
image = cv2.imread('img.jpg', 0)  # 以灰度模式读取图像
ret, binary_image = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY)

# 创建一个与图像大小相同的标记图
height, width = binary_image.shape
markers = np.zeros((height, width), dtype=np.int32)

# 定义一个颜色映射
color_map = {
    1: (0, 0, 255),  # 红色
    2: (0, 255, 0),  # 绿色
    3: (255, 0, 0),  # 蓝色
    4: (0, 255, 255),  # 黄色
    # 您可以根据需要添加更多颜色
}

# 连通区域计数
region_count = 0

# 定义8个邻域的偏移
neighbor_offsets = [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]

# 开始查找连通区域
for y in range(height):
    for x in range(width):
        if binary_image[y, x] == 255 and markers[y, x] == 0:
            region_count += 1
            markers[y, x] = region_count
            queue = [(y, x)]

            while queue:
                current_y, current_x = queue.pop(0)

                for dy, dx in neighbor_offsets:
                    ny, nx = current_y + dy, current_x + dx

                    if 0 <= ny < height and 0 <= nx < width and binary_image[ny, nx] == 255 and markers[ny, nx] == 0:
                        markers[ny, nx] = region_count
                        queue.append((ny, nx))

# 将连通区域标记为不同颜色
result_image = np.zeros((height, width, 3), dtype=np.uint8)
for y in range(height):
    for x in range(width):
        if markers[y, x] > 0:
            result_image[y, x] = color_map[markers[y, x]]

# 显示结果图像
cv2.imshow('Connected Components', result_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

         这段代码首先读取了一个灰度图像(也可以使用彩色图像),将其转换为二值图像。然后,它使用BFS算法查找连通区域,对不同的连通区域进行标记,并将它们标记为不同的颜色。最后,它显示带有标记的结果图像。

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

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

相关文章

python的搜索引擎系统设计与实现 计算机竞赛

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; python的搜索引擎系统设计与实现 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;5分创新点&#xff1a;3分 该项目较为新颖&#xff…

申请400电话需要的条件及办理流程

随着企业的发展和市场竞争的加剧&#xff0c;越来越多的企业开始意识到拥有一个400电话的重要性。400电话是一种以400开头的电话号码&#xff0c;可以为企业提供统一的客户服务热线&#xff0c;提高客户满意度和企业形象。下面将介绍申请400电话所需要的条件以及办理流程。 一…

python篇---python打印报错行

Python打印报错行的实现 步骤1&#xff1a;捕获异常步骤2&#xff1a;输出异常信息步骤3&#xff1a;打印报错行完整代码示例 作为一名开发者&#xff0c;我将教你如何在Python中打印报错行。这个技巧对于定位和解决代码中的错误非常有帮助。下面是详细的步骤和代码说明。 步…

小程序之如何学习一个新的知识,首先就是通过官网进行讲解!!(2)

⭐⭐ 小程序专栏&#xff1a;小程序开发专栏 ⭐⭐ 个人主页&#xff1a;个人主页 目录 ​编辑 一.前言 二.视图层 2.1 WXML的使用&#xff1a; 2.2 事件系统​编辑 三逻辑层&#xff08;生命周期&#xff09;--跳转页面 3.1生命周期 3.2 案例 3.3总结 今天就是给大家…

计算机网络中的CSMA/CD算法的操作流程(《自顶向下》里的提炼总结)

具有碰撞检测的载波侦听多路访问&#xff08;CSMA/CD算法&#xff09; 以下内容总结&#xff0c;对应《计算机网络自顶向下第七版》第六章链路层和局域网P299 操作流程&#xff1a; NIC&#xff08;适配器&#xff0c;即网络接口&#xff09;从网络层接收数据报&#xff0c;…

微信小程序前端生成动态海报图

//页面显示<canvas id"myCanvas" type"2d" style" width: 700rpx; height: 600rpx;" />onShareShow(e){var that this;let user_id wx.getStorageSync(user_id);let sharePicUrl wx.getStorageSync(sharePicUrl);if(app.isBlank(user_i…

基于OFDM通信系统的PAPR抑制算法matlab仿真,对比IPTS,OPTS,CEPTS三种算法

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1、IPTS算法 4.2、OPTS算法 4.3、CEPTS算法 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 for k1:Nframesif mod(k,10) 0k/10end%产生…

Python自动化运维实战——Telnetlib和Netmiko自动化管理网络设备

❤️博客主页&#xff1a; iknow181&#x1f525;系列专栏&#xff1a; Python、JavaSE、JavaWeb、CCNP&#x1f389;欢迎大家点赞&#x1f44d;收藏⭐评论✍ 目录 一、前言 二、准备工作 三、Telnetlib Telnetlib介绍 Telnetlib模块及操作方法介绍 Telnetlib配置设备 T…

Unity SRP 管线【第一讲:自定义渲染管线】

来源&#xff1a; https://edu.uwa4d.com/lesson-detail/282/1308/0?isPreviewfalse 文章目录 来源&#xff1a;自定义渲染管线前置工作渲染管线资产渲染管线实例 正式渲染CommandBuffer清除渲染目标剔除&#xff08;Culling&#xff09;绘制绘制集合体 透明和不透明物体分开…

MySQL学习(二)——MySQL内置函数

文章目录 1. 函数1.1 字符串函数1.2 数值函数1.3 日期函数1.4 流程函数 2. 约束2.1 概述2.2 外键约束2.2.1 外键使用2.2.2 删除/更新行为 1. 函数 和其他编程语言一样&#xff0c;MySQL也有函数的定义。函数 是指一段可以直接被另一段程序调用的程序或代码。 也就意味着&#…

jmeter接口测试实战:接口加密、接口解密、签名sign接口实战详解

在接口测试中&#xff0c;签名&#xff08;sign&#xff09;是一种重要的加密方式&#xff0c;用于保障数据传输的安全性和完整性。在这篇文章中&#xff0c;我们将通过一个具体的案例来学习如何使用 JMeter 进行签名接口的测试&#xff0c;并用 Python 代码进行实战演示。 比…

集成友盟qq互联分享,导出风险问题处理

处理方案&#xff1a;移除 android:exported"true"即可。 注意友盟SDK QQ share 里默认配置是android:exported"true"&#xff0c;所以要覆盖即可。

为什么CDN能创造这么利益

互联网的快速发展带来了更多的在线内容和应用&#xff0c;但同时也引发了对网站性能的高要求。用户对快速加载的期望越来越高&#xff0c;这就需要采用高效的内容分发解决方案。在这方面&#xff0c;CDN&#xff08;内容分发网络&#xff09;扮演了关键角色&#xff0c;通过其分…

uniapp(uncloud) 使用生态开发接口详情2(使用 schema创建数据, schema2code创建页面, iconfont 引入项目)

上一篇介绍如何创建项目,接下来该是如何使用 在项目中pages 目录下,新建界面 项目运行,浏览器中用账号密码登录, 新建一级和二级页面 2.1 系统管理 > 菜单管理 (新增一级界面) 2.2 找到刚刚创建的菜单, 操作行有 子菜单(点击) 用DB Schema创建页面, 3.1 在uniCloud > d…

大规模语言模型人类反馈对齐--RLHF

大规模语言模型在进行监督微调后&#xff0c; 模型具备了遵循指令和多轮对话的能力&#xff0c; 具备了初步与用户进行对话 的能力。然而&#xff0c; 大规模语言模由于庞大的参数量和训练语料&#xff0c; 其复杂性往往难以理解和预测。当这些模型被部署 时&#xff0c; 它们可…

经济不景气时,企业如何通过反向竞价节省成本?

在经济不景气时期&#xff0c;企业往往被迫寻找创新方法来削减成本&#xff0c;争取提高盈利。其中一种越来越受欢迎的方法就是使用反向竞价。 反向竞价是一种采购策略&#xff0c;它颠覆了传统的采购流程&#xff0c;允许供应商竞争买方的业务。这种方法可以节省大量成本&…

退税政策线上VR互动科普展厅为税收工作带来了强大活力

缴税纳税是每个公民应尽的义务和责任&#xff0c;由于很多人缺乏专业的缴税纳税操作专业知识和经验&#xff0c;因此为了提高大家的缴税纳税办事效率和好感度&#xff0c;越来越多地区税务局开始引进VR虚拟现实、web3d开发和多媒体等技术手段&#xff0c;基于线上为广大公民提供…

C# Winform编程(2)常用控件

C# Winform编程&#xff08;2&#xff09;常用控件 常用控件 常用控件 标签&#xff0c;文本&#xff0c;按钮&#xff0c;列表框&#xff0c;组合框等的使用 Program.cs using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks…

Python-pyecharts和pandas库

目录 pyecharts库 pandas库 示例1 示例2 pyecharts库 pyecharts是一个基于Python的交互式数据可视化库&#xff0c;旨在帮助用户轻松地创建各种类型的图表和可视化效果。该库是在Echarts开源项目的基础上开发的&#xff0c;Echarts是一款由百度开发的优秀的数据可视化工具。…

静力触探数据智能预处理(3)

静力触探数据智能预处理&#xff08;3&#xff09; 前言 将钻探、物探、静力触探三种数据放在一起对比分析&#xff0c;三种方法间存在尚不明确的物性联系。利用某规范进行土的分类&#xff0c;得出了全是砂土的错误结论&#xff0c;非专业编写&#xff0c;仅供参考。 1、对…