【深度优先搜索】和【广度优先搜索】的区别介绍

news/2024/7/20 21:20:10 标签: 深度优先, 宽度优先, 算法

一. 前言

深度优先搜索(Depth-First Search,DFS)和广度优先搜索(Breadth-First Search,BFS)是两种常见的图搜索算法。它们的主要区别在于搜索的方式和顺序不同。

二. 区别

1. DFS的搜索方式是:

从某个节点出发,沿着一条路径直到底部,然后返回到前一个节点,继续搜索下一条路径,直到搜索完整张图。DFS使用栈或者递归来实现搜索过程。

具体步骤如下:

  • 访问起始结点;
  • 递归地访问第一个未被访问的相邻结点,如果没有未被访问的相邻结点,则回溯到上一个结点继续递归;
  • 依次访问和递归每个未被访问的相邻结点,直到找到目标结点或到达叶子结点为止。

2. BFS的搜索方式是:

从某个节点出发,将其所有邻接节点加入到队列中,然后依次访问队列中的节点,将其邻接节点加入到队列中,以此类推,直到搜索完整张图。BFS使用队列来实现搜索过程。

具体步骤如下:

  • 将起始结点放入队列中;

  • 访问队列头部结点,将其未访问过的相邻结点加入队列尾部;

  • 将队列头部结点出队列;

  • 重复步骤 2 和 3,直到队列为空或找到目标结点。

三. 代码示例

1. 深度优先搜索代码示例:

示例一

def dfs(graph, start, target, path=[]):
    # 记录路径
    path = path + [start]
    # 到达目标结点,返回路径
    if start == target:
        return path
    # 遍历相邻结点
    for node in graph[start]:
        if node not in path:
            newpath = dfs(graph, node, target, path)
            if newpath:
                return newpath
    return None

示例二

class Graph:
    def __init__(self, graph_dict=None):
        if graph_dict is None:
            graph_dict = {}
        self.__graph_dict = graph_dict
 
    def add_vertex(self, vertex):
        if vertex not in self.__graph_dict:
            self.__graph_dict[vertex] = []
 
    def add_edge(self, edge):
        edge = set(edge)
        (vertex1, vertex2) = tuple(edge)
        if vertex1 in self.__graph_dict:
            self.__graph_dict[vertex1].append(vertex2)
        else:
            self.__graph_dict[vertex1] = [vertex2]
 
    def dfs(self, start, visited=None):
        if visited is None:
            visited = set()
        visited.add(start)
        print(start)
        for next in self.__graph_dict[start] - visited:
            self.dfs(next, visited)
        return visited
 
 
graph = {"A": {"B", "C"},
         "B": {"A", "D", "E"},
         "C": {"A", "F"},
         "D": {"B"},
         "E": {"B", "F"},
         "F": {"C", "E"}}
 
g = Graph(graph)
print("Depth First Search:")
g.dfs("A")

运行结果
在这里插入图片描述

2. 广度优先搜索代码示例:

示例一

from collections import deque

# 使用队列实现 BFS
def bfs(graph, start, target):
    # 使用 deque 实现双端队列
    queue = deque()
    queue.append(start)
    visited = set()
    visited.add(start)
    while queue:
        # 出队列
        node = queue.popleft()
        # 到达目标结点,返回
        if node == target:
            return True
        # 遍历相邻结点
        for neighbor in graph[node]:
            # 未访问过的结点入队列
            if neighbor not in visited:
                visited.add(neighbor)
                queue.append(neighbor)
    # 没有找到目标结点
    return False

示例二

from collections import deque
 
 
class Graph:
    def __init__(self, graph_dict=None):
        if graph_dict is None:
            graph_dict = {}
        self.__graph_dict = graph_dict
 
    def add_vertex(self, vertex):
        if vertex not in self.__graph_dict:
            self.__graph_dict[vertex] = []
 
    def add_edge(self, edge):
        edge = set(edge)
        (vertex1, vertex2) = tuple(edge)
        if vertex1 in self.__graph_dict:
            self.__graph_dict[vertex1].append(vertex2)
        else:
            self.__graph_dict[vertex1] = [vertex2]
 
    def bfs(self, start):
        visited, queue = set(), deque([start])
        visited.add(start)
        while queue:
            vertex = queue.popleft()
            print(vertex)
            for neighbour in self.__graph_dict[vertex]:
                if neighbour not in visited:
                    visited.add(neighbour)
                    queue.append(neighbour)
 
 
graph = {"A": {"B", "C"},
         "B": {"A", "D", "E"},
         "C": {"A", "F"},
         "D": {"B"},
         "E": {"B", "F"},
         "F": {"C", "E"}}
 
g = Graph(graph)
print("Breadth First Search:")
g.bfs("A")

运行结果
在这里插入图片描述

四. 总结:

  • 深度优先搜索:倾向于深度遍历图中的分支,直到遇到叶子节点或目标节点;
  • 广度优先搜索:倾向于先遍历离起始节点较近的节点,然后逐步向下遍历。

http://www.niftyadmin.cn/n/5146541.html

相关文章

路由器ip地址怎么设置才能上网

在互联网时代,路由器已经成为了我们生活中不可或缺的一部分。而路由器的IP地址则是路由器配置的关键。那么,如何设置路由器的IP地址才能上网呢?虎观代理小二二将为您提供详细的步骤和指导。 一、确认路由器IP地址 在开始设置路由器的IP地址…

企业中台如何进行测试(下篇)

《企业中台如何进行测试》包含了主数据治理测试、统一认证测试、业务集成测试、门户建设测试、数据分析测试等内容。由于篇幅较长,将分为上、下两个篇章与大家分享,在上篇主要从主数据治理和统一认证两个方面对企业中台的测试内容进行介绍,下…

语音信号的线性预测分析、合成及MATLAB编程设计实现

需要的基础:AR模型、列文森-杜宾递推法 推荐阅读: 基于线性预测的语音编码原理解析 基于线性预测的语音编码原理解析 这篇文章和上一篇类似 语音信号的线性预测分析及其Matlab源码 这篇文章是要付费看的,但是他能预览的那部分写的确实好 语…

SQL server数据库定时搜索

问题现象 出现下图问题,导致连接该数据库的程序不能正常启动 解决办法 定时搜索数据库 脚本 # 设置数据库名称 # 设置定时任务时间# 生成定时任务执行sql文件 sql语句 USE [master] GO ALTER DATABASE volador SET RECOVERY SIMPLE WITH NO_WAIT GO ALTER DA…

力扣第474题 一和零 c++ 动态规划 01背包

题目 474. 一和零 中等 相关标签 数组 字符串 动态规划 给你一个二进制字符串数组 strs 和两个整数 m 和 n 。 请你找出并返回 strs 的最大子集的长度,该子集中 最多 有 m 个 0 和 n 个 1 。 如果 x 的所有元素也是 y 的元素,集合 x 是集合 y…

C代码内存区域划分

C代码内存区域划分 1、初始化不为零的(全局变量、静态全局变量和静态局部变量)放在.data段 2、初始化为0,和未初始化的(全局变量、静态全局变量和静态局部变量)放在.bss 3、编译阶段未初始化的全局变量放在COM块&…

Idea 对容器中的 Java 程序断点远程调试

第一种:简单粗暴型 直接在java程序中添加log.info(),根据需要打印信息然后打包覆盖,根据日志查看相关信息 第二种:远程调试 在IDEA右上角点击编辑配置设置相关参数在Dockerfile中加入 "-jar", "-agentlib:jdwp…

python---数据类型(列表)

组织列表 使用sort()方法对列表永久性排序 按照字母顺序排序: motorcycles [chunlan, yamaha, dayun, jianshe]motorcycles.sort()print(motorcycles) 字母倒序: motorcycles [chunlan, yamaha, dayun, jianshe]motorcycles.sort(reverseTrue)pri…