首页 > 编程语言 >【图计算算法‌】广度优先搜索(BFS)算法

【图计算算法‌】广度优先搜索(BFS)算法

时间:2024-09-28 22:48:49浏览次数:7  
标签:优先 搜索算法 BFS 算法 搜索 广度 节点

目录

一、广度优先搜索算法概述

1.1 算法原理

1.2 算法步骤

1.3 算法特点

二、广度优先搜索算法优缺点和改进

2.1 广度优先搜索算法优点

2.2  广度优先搜索主算法缺点

2.3  广度优先搜索算法改进

三、广度优先搜索算法编程实现

3.1  广度优先搜索算法C语言实现

3.2  广度优先搜索算法JAVA实现

3.3  广度优先搜索算法python实现

四、广度优先搜索算法的应用

4.1. 社交网络分析

4.2. 路由协议

4.3. 图像处理

4.4. 游戏和迷宫求解

4.5. 图的遍历和搜索

4.6. 路径规划

4.7. 拼写检查

4.8. 编译器和代码优化

五、广度优先搜索算法发展趋势

5.1. 算法优化与效率提升

5.2. 应用领域的拓展

5.3. 与其他技术的融合

5.4. 安全性与隐私保护


一、广度优先搜索算法概述

        广度优先搜索(BFS)算法是一种在图或树数据结构中广泛应用的遍历算法。它按照从起始节点开始,逐层向外扩展的顺序访问节点,直到找到目标节点或遍历完所有可达的节点。以下是BFS算法的详细概述:

1.1 算法原理

  • 起点开始:算法从指定的起始节点开始。

  • 逐层遍历:首先访问起始节点的所有相邻节点,然后依次访问这些相邻节点的所有未被访问的相邻节点,逐层向外扩展。

  • 先进先出:BFS算法使用队列(Queue)这一先进先出的数据结构来存储待访问的节点,以保证节点按照被发现的顺序被访问。

1.2 算法步骤

  1. 初始化:创建一个队列Q,将起始节点放入队列中,并标记为已访问。

  2. 访问节点:从队列中取出一个节点,访问它。

  3. 扩展邻居:遍历该节点的所有未被访问的相邻节点,将它们加入队列中,并标记为已访问。

  4. 重复过程:重复步骤2和步骤3,直到队列为空,即所有可达的节点都被访问过。

1.3 算法特点

  • 按层级遍历:BFS算法按照节点的层级进行遍历,先访问离起始节点近的节点。

  • 找到最短路径:在无权图中,BFS算法可以用来找到从起始节点到目标节点的最短路径。

  • 空间复杂度:BFS算法的空间复杂度主要取决于队列的大小,最坏情况下为O(V),其中V是图中节点的数量。

  • 时间复杂度:BFS算法的时间复杂度为O(V+E),其中V是节点的数量,E是边的数量。

二、广度优先搜索算法优缺点和改进

2.1 广度优先搜索算法优点

  1. 简单直观:算法实现简单,容易理解和实现。

  2. 找到最短路径:在无权图中,广度优先搜索算法能够找到从起始节点到目标节点的最短路径(即边数最少的路径)。

  3. 非递归实现:广度优先搜索可以使用队列等非递归数据结构实现,避免了递归可能带来的栈溢出问题。

2.2  广度优先搜索主算法缺点

  1. 空间复杂度较高:在最坏情况下,需要存储图中所有节点,因此空间复杂度较高。

  2. 不适合大图:对于节点数非常多的图,广度优先搜索可能会因为空间复杂度过高而难以处理。

  3. 不保证最优解(在某些情况下):在有权图中,广度优先搜索不一定能找到从起始节点到目标节点的最短路径(按边的权重计算)。

2.3  广度优先搜索算法改进

  1. 优化存储结构:使用更高效的数据结构来存储节点的访问状态,如位图(bitmap)等,以减少内存占用。

  2. 剪枝策略:在搜索过程中,根据问题的特点,设计合理的剪枝策略来避免不必要的搜索,从而提高搜索效率。

  3. 双向搜索:对于某些问题,可以同时从起始节点和目标节点开始进行广度优先搜索,当两个搜索过程在某个节点相遇时,即可找到一条路径。这种方法可以大大减少搜索空间,提高搜索效率。

  4. 启发式搜索:将广度优先搜索与启发式信息结合,形成启发式搜索算法(如A*算法),以找到更优的解。启发式信息可以是基于节点与目标节点之间距离的估计值。

  5. 并行计算:利用并行计算技术,将广度优先搜索过程分布到多个处理器或计算机上同时执行,以加快搜索速度。

三、广度优先搜索算法编程实现

3.1  广度优先搜索算法C语言实现

#include <stdio.h>
#include <stdlib.h>
 
#define MAX_VERTEX_NUM 20
 
// 定义图的结构体
typedef struct Graph {
    int vertex[MAX_VERTEX_NUM];      // 存储顶点信息
    int edge[MAX_VERTEX_NUM][MAX_VERTEX_NUM];    // 存储边信息
    int numVertexes, numEdges;       // 图的当前顶点数和边数
} Graph;
 
// 创建图的函数
Graph* createGraph() {
    Graph* graph = (Graph*)malloc(sizeof(Graph));
    graph->numVertexes = 6;
    graph->numEdges = 10;
 
    // 初始化顶点
    for (int i = 0; i < graph->numVertexes; i++) {
        graph->vertex[i] = i;
    }
 
    // 初始化边
    int edges[MAX_VERTEX_NUM][2] = {
        {0, 1}, {0, 2}, {1, 2}, {1, 3}, {2, 4},
        {3, 4}, {3, 5}, {4, 5}
    };
 
    // 初始化边的信息
    for (int i = 0; i < graph->numEdges; i++) {
        graph->edge[edges[i][0]][edges[i][1]] = 1;
        graph->edge[edges[i][1]][edges[i][0]] = 1;
    }
 
    return graph;
}
 
// 广度优先搜索算法
void BFS(Graph* graph, int start) {
    int queue[MAX_VERTEX_NUM], front = -1, rear = -1; // 定义一个队列
    int visited[MAX_VERTEX_NUM] = {0}; // 访问标志数组
    int i;
 
    // 访问起始顶点并标记
    visited[start] = 1;
    printf("%d ", start);
 
    // 起始顶点入队
    rear++;
    queue[rear] = start;
 
    // 当队列不为空时执行
    while (front != rear) {
        front = (front + 1) % MAX_VERTEX_NUM;
        int vertex = queue[front];
 
        // 遍历所有顶点
        for (i = 0; i < graph->numVertexes; i++) {
            // 如果边存在且顶点未被访问,则访问并入队
            if (graph->edge[vertex][i] == 1 && visited[i] == 0) {
                visited[i] = 1;
                printf("%d ", i);
                rear = (rear + 1) % MAX_VERTEX_NUM;
                queue[rear] = i;
            }
        }
    }
}
 
int main() {
    Graph* graph = createGraph();
    printf("广度优先搜索结果: ");
    BFS(graph, 0);
    printf("\n");
    return 0;
}

        这段代码首先定义了图的结构体,并实现了创建图和广度优先搜索算法的函数。在main函数中,我们创建了一个简单的图,并从顶点0开始进行了广度优先搜索,打印出了访问的顶点序列。这个例子提供了一个清晰的算法实现,并且易于理解和调试。

3.2  广度优先搜索算法JAVA实现

import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
 
public class BFS {
 
    public static void bfs(boolean[][] maze, int[] start, int[] end) {
        int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; // 右, 下, 左, 上
        Queue<int[]> queue = new LinkedList<>();
        queue.offer(start);
        maze[start[0]][start[1]] = true; // 表示该位置已访问
 
        while (!queue.isEmpty()) {
            int[] current = queue.poll();
            if (Arrays.equals(current, end)) {
                // 找到了出口
                break;
            }
            for (int[] direction : directions) {
                int nextX = current[0] + direction[0];
                int nextY = current[1] + direction[1];
                if (inBounds(maze, nextX, nextY) && !maze[nextX][nextY]) {
                    queue.offer(new int[]{nextX, nextY});
                    maze[nextX][nextY] = true; // 表示该位置已访问
                }
            }
        }
    }
 
    private static boolean inBounds(boolean[][] maze, int x, int y) {
        return x >= 0 && x < maze.length && y >= 0 && y < maze[x].length;
    }
 
    // 测试代码
    public static void main(String[] args) {
        boolean[][] maze = {
            {false, false, true, true, false},
            {true, false, false, true, false},
            {true, true, false, true, true},
            {false, false, true, false, false}
        };
        int[] start = {0, 0}; // 起点
        int[] end = {3, 4}; // 终点
        bfs(maze, start, end);
    }
}

        这段代码实现了一个简单的二维数组的BFS算法,用于解决迷宫问题。它定义了一个方向数组来表示搜索的四个方向,并使用一个链接队列来存储待访问的节点。在主函数中,我们定义了一个迷宫和起点终点,并调用bfs函数进行搜索。

3.3  广度优先搜索算法python实现

from collections import deque
 
def bfs(graph, start):
    visited = set()  # 访问过的节点集合
    queue = deque([start])  # 初始化队列
 
    while queue:
        node = queue.popleft()  # 从队列左侧弹出节点
        if node not in visited:
            visited.add(node)  # 标记为已访问
            for neighbor in graph[node]:  # 访问所有邻居节点
                if neighbor not in visited:
                    queue.append(neighbor)  # 将未访问的邻居加入队列
    return visited
 
# 示例图
graph = {
    'A': ['B', 'C'],
    'B': ['A', 'D', 'E'],
    'C': ['A', 'F'],
    'D': ['B'],
    'E': ['B', 'F'],
    'F': ['C', 'E']
}
 
# 从节点'A'开始进行BFS搜索
print(bfs(graph, 'A'))

        这段代码定义了一个bfs函数,它接受一个图和一个起始节点作为参数,并返回从起始节点开始的所有可达节点。在这个例子中,图是一个字典,其中键是节点,值是相邻节点的列表。使用deque作为队列来实现BFS算法。

四、广度优先搜索算法的应用

        广度优先搜索算法(Breadth-First Search, BFS)是一种用于遍历或搜索树或图的算法,它的基本思想是从起始节点开始,先访问离起始节点最近的节点,然后逐步向外扩展,直到找到目标节点或遍历完整个图。以下是广度优先搜索算法的一些主要应用:

4.1. 社交网络分析

        在社交网络中,广度优先搜索可以用于分析用户之间的关系,找到从某个用户到目标用户的最近路径。这有助于理解社交网络的结构,发现潜在的联系或群组,以及进行社交网络的可视化等。

4.2. 路由协议

        在计算机网络中,广度优先搜索被广泛应用于路由协议的路由发现过程。通过从源节点开始,逐层向外搜索,直到找到目标节点,可以确定从源节点到目标节点的最佳路径。这有助于实现数据的快速、可靠传输。

4.3. 图像处理

        在图像处理领域,广度优先搜索可以用于图像分割、边缘检测等任务。通过将图像看作一个图结构,其中像素点作为节点,相邻像素点之间的相似度作为边的权重,可以利用广度优先搜索来识别图像中的不同区域或边缘。

4.4. 游戏和迷宫求解

        在游戏和迷宫求解问题中,广度优先搜索可以用来找到从起点到终点的最短路径。通过逐层遍历迷宫的所有可能路径,直到找到通往终点的路径,这种方法简单且有效。

4.5. 图的遍历和搜索

        在更广泛的图论问题中,广度优先搜索是一种基本的遍历和搜索算法。它可以用于检查图的连通性、计算图的直径、发现图中的环等。

4.6. 路径规划

        在路径规划问题中,如地图导航、机器人路径规划等,广度优先搜索可以用来找到从起点到终点的最优路径。通过考虑不同的移动方向和障碍物,算法可以计算出一条最短或最优的路径。

4.7. 拼写检查

        在拼写检查器中,广度优先搜索可以用来计算将错拼的单词改成正确的单词所需的最少编辑次数。这通常涉及到对单词进行插入、删除或替换字符的操作。

4.8. 编译器和代码优化

        在编译器的设计和代码优化过程中,广度优先搜索可以用于分析代码中的依赖关系、确定变量的作用域等。这有助于编译器生成更高效、更优化的代码。

        总之,广度优先搜索算法在多个领域都有广泛的应用,其核心思想是按照节点间的距离进行遍历和搜索,从而找到问题的解决方案。

五、广度优先搜索算法发展趋势

        广度优先搜索算法(BFS)作为图论中的一个基础且重要的算法,其发展趋势与计算机科学及图论领域的发展密切相关。以下是对广度优先搜索算法发展趋势的归纳:

5.1. 算法优化与效率提升

  • 并行化与分布式处理:随着并行计算和分布式系统的发展,广度优先搜索算法也逐渐向并行化和分布式处理方向发展。这有助于在大规模图数据中实现更高效的搜索和遍历。

  • 算法改进:研究者们不断探索新的算法改进策略,如使用更高效的队列实现方式、优化节点访问顺序等,以进一步提高算法的执行效率和性能。

5.2. 应用领域的拓展

  • 社交网络分析:在社交网络领域,广度优先搜索算法被广泛应用于好友推荐、信息传播路径分析等方面。随着社交网络的不断发展,其应用场景将更加广泛。

  • 智能交通系统:在智能交通系统中,广度优先搜索算法可用于路径规划、车辆调度等方面,以优化交通流、减少拥堵。

  • 其他领域:此外,广度优先搜索算法还广泛应用于游戏开发、网络爬虫、数据库查询优化等领域,为这些领域的发展提供了有力的支持。

5.3. 与其他技术的融合

  • 人工智能与机器学习:随着人工智能和机器学习技术的发展,广度优先搜索算法可以与这些技术相结合,实现更智能化的搜索和决策。例如,利用机器学习算法预测节点的访问顺序,从而优化搜索过程。

  • 自然语言处理与语义网:在自然语言处理和语义网领域,广度优先搜索算法可用于语义搜索、知识图谱构建等方面,以支持更复杂的查询和推理任务。

5.4. 安全性与隐私保护

  • 数据加密与隐私保护:在处理敏感数据时,广度优先搜索算法需要考虑数据加密和隐私保护问题。未来的发展趋势可能包括在算法设计中融入加密技术,以确保数据的安全性和隐私性。

        综上所述,广度优先搜索算法的发展趋势包括算法优化与效率提升、应用领域的拓展、与其他技术的融合以及安全性与隐私保护等方面。随着计算机科学的不断发展,广度优先搜索算法将在更多领域发挥重要作用,并不断推动相关技术的进步和发展。

标签:优先,搜索算法,BFS,算法,搜索,广度,节点
From: https://blog.csdn.net/xiaoyingxixi1989/article/details/142594989

相关文章

  • 基于秃鹰算法优化的最小交叉熵图像多阈值分割
    智能优化算法应用:基于秃鹰算法优化的最小交叉熵图像多阈值分割文章目录智能优化算法应用:基于秃鹰算法优化的最小交叉熵图像多阈值分割1.前言2.最小交叉熵阈值分割原理3.基于秃鹰优化的多阈值分割4.算法结果:5.参考文献:6.Matlab代码摘要:本文介绍基于最小交叉熵的图像......
  • 代码随想录算法训练营第三天|203.移除链表元素,707.设计链表,206.反转链表
    203.移除链表元素文章链接:https://programmercarl.com/0203.移除链表元素.html#算法公开课视频讲解:https://www.bilibili.com/video/BV18B4y1s7R9题目出处:https://leetcode.cn/problems/remove-linked-list-elements/卡哥在这里讲解了为什么要使用虚拟头节点,以及使用和不使......
  • 算法复杂度-空间
    一.空间复杂度空间复杂度也是一个数学表达式,是对一个算法在运行过程中因为算法的需要额外临时开辟的空间。空间复杂度不是程序占用了多少个bytes的空间,因为常规情况每个对象大小差异不会很大,所以空间复杂度算的是变量的个数。空间复杂度的计算规则基本跟时间复杂......
  • 算法复杂度之时间复杂度
    一.数据结构前言1.1数据结构数据结构(Datastructure)是计算机存储,组织数据的方式,指互相之间存在一种或多种特定关系的数据元素的集合。没有一种单一的数据结构对所有用途都有用,所以要学习各式各样的数据结构,如:线性表,树,图,哈希等。(不仅能存储数据,还能够管理数据)1.2算法......
  • 精通推荐算法31:行为序列建模之ETA — 基于SimHash实现检索索引在线化
    1 行为序列建模总体架构2SIM模型的不足和为什么需要ETA模型SIM实现了长周期行为序列的在线建模,其GSU检索单元居功至伟。但不论Hard-search还是Soft-search,都存在如下不足:GSU检索的目标与主模型不一致。Hard-search通过类目属性来筛选历史行为,但不同类目不代表相关度低,比......
  • 关于算法复杂度
    1.复杂度的概念算法在编写成可执⾏程序后,运⾏时需要耗费时间资源和空间(内存)资源。因此衡量⼀个算法的好坏,⼀般是从时间和空间两个维度来衡量的,即时间复杂度和空间复杂度。    时间复杂度主要衡量⼀个算法的运⾏快慢,⽽空间复杂度主要衡量⼀个算法运⾏所......
  • 无人机之视觉导航算法篇
    一、图像采集与预处理图像采集:无人机通过其搭载的摄像头或其他视觉传感器实时采集周围环境的图像信息。图像预处理:对采集到的图像进行预处理,包括滤波、降噪、增强等操作,以提高图像的质量和清晰度,为后续的特征提取和匹配奠定基础。二、特征提取与匹配特征提取:从预处理后的图......
  • 算法训练营第三天| 203.移除链表元素、707.设计链表、206.反转链表
    203.移除链表元素状态:完成个人思路:首先令head符合条件,之后判断这个head是否为空,空的话返回空节点;非空的话继续进行。令pre=head;cur=head->next,只要cur非空,就判断cur的值的情况,如果需要删除,就改变pre->next和cur;如果不需要删除就继续检查下一个。看完讲解视频之后的想法:我......
  • 算法训练营第二天| 209.长度最小的子数组、59.螺旋矩阵II
    209.长度最小的子数组状态:没写出来->确认自己的想法是对的之后写出来了!!!初始思路:因为子数组是连续的,所以可以采用滑动窗口,我把这个窗口设置为左闭右闭,所以初始左右边界为0。之后先移动右指针,使得找到第一个和大于等于target的子数组,记录其长度,之后再移动左指针一位,再找第二个......
  • java基于协同过滤算法的springboot的煤矿员工健康管理系统(源码+文档+调试+vue+前后端
    收藏关注不迷路!!......