数据结构基础之广度优先遍历(BFS),深度优先遍历(DFS)

大话数据结构-图的深度优先遍历和广度优先遍历 数据结构中图的深度优先遍历、广度优先遍历定义,邻接矩阵、邻接表、逆邻接表、十字链表、邻接多重表和边集数组的深度优先遍历实现和广度优先遍历实现。 阅读详情

广度优先遍历(BFS)

概念

广度优先遍历(Breadth First Search, BFS)是一种图的遍历算法。它从一个节点开始,先访问起始节点,然后遍历它的所有直接相连的节点。然后对这些相连节点依次进行遍历,直到图中的所有节点都被访问一次。
广度优先遍历的主要特点是:

  • 它利用了队列的先进先出特点, visiting nodes in the order they are discovered.
  • 遍历过的节点会被标记,防止重复访问。
  • 先访问起点,然后按照距离起点的远近顺序遍历周边节点。近者优先访问。
  • 每次都从当前节点领域未被访问过的节点中选取距离最近的节点访问。
  • 直到所有可达节点访问完毕,算法结束。
    广度优先遍历的实现步骤:
  1. 初始化队列,访问起点并入队。
  2. 当队列不为空时,继续迭代:
  • 出队列头节点并访问。
  • 将该节点的所有未访问相邻节点入队。
  • 标记该节点为已访问。
  1. 重复步骤2直到队列为空,算法结束。
    广度优先遍历时间复杂度为 O(V+E),空间复杂度为 O(V),其中 V 为图的节点数,E 为图的边数。广度优先遍历主要应用在最短路径等问题中。

以最短路径为例子

当涉及到查找最短路径时,最常用的算法是 Dijkstra’s Algorithm(迪克斯特拉算法)。这个算法用于查找图中从起始节点到其他所有节点的最短路径。在下面的代码示例中,将使用 JavaScript 来实现 Dijkstra’s Algorithm。

function dijkstra(graph, start) {
  const distances = {};
  for (const node in graph) {
    distances[node] = Infinity;
  }
  distances[start] = 0;

  const priorityQueue = new PriorityQueue();
  priorityQueue.enqueue(start, 0);

  while (!priorityQueue.isEmpty()) {
    const { element: current_node, priority: current_distance } = priorityQueue.dequeue();

    if (current_distance > distances[current_node]) {
      continue;
    }

    for (const neighbor in graph[current_node]) {
      const distance = current_distance + graph[current_node][neighbor];
      if (distance < distances[neighbor]) {
        distances[neighbor] = distance;
        priorityQueue.enqueue(neighbor, distance);
      }
    }
  }

  return distances;
}

// 优先队列实现
class PriorityQueue {
  constructor() {
    this.queue = [];
  }

  enqueue(element, priority) {
    this.queue.push({ element, priority });
    this.sort();
  }

  dequeue() {
    return this.queue.shift();
  }

  isEmpty() {
    return this.queue.length === 0;
  }

  sort() {
    this.queue.sort((a, b) => a.priority - b.priority);
  }
}

// 示例图的邻接字典表示,权重用于表示边的距离
const graph = {
  'A': { 'B': 1, 'C': 4 },
  'B': { 'D': 3 },
  'C': { 'D': 1 },
  'D': {}
};

const startNode = 'A';
const shortestDistances = dijkstra(graph, startNode);
console.log(`Shortest distances from node ${startNode} to all other nodes:`);
console.log(shortestDistances);

在上面的代码中,使用了一个优先队列来帮助处理节点的优先级。优先队列可以确保在每次迭代中,都选择最短距离的节点作为下一个当前节点,从而确保 Dijkstra’s Algorithm 的正确性。

这个代码示例中的 graph 表示一个带权重的图的邻接字典表示。startNode 是要查找最短路径的起始节点。算法会返回一个包含所有节点到起始节点的最短距离的对象。在示例图中,从节点 A 出发,算法会返回节点 A 到其他所有节点的最短距离。

需要注意,这里的 PriorityQueue 是一个简化的实现,实际上在生产环境中可以使用更高效的优先队列实现,例如 Fibonacci Heap 或二叉堆。同时,这里假设图中没有负权边。对于包含负权边的图,需要使用 Bellman-Ford 算法来查找最短路径。

深度优先遍历

概念

深度优先遍历(Depth First Search, DFS)是另一种图的遍历算法。与广度优先遍历不同,它从起始节点出发,尽可能深的搜索某一条路径,直到无法继续遍历为止,然后再回溯进行其他路径的遍历。
深度优先遍历的主要特点是:

  • 利用栈的先进后出特点,按路径顺序访问节点。
  • 沿着路径遍历到不能继续走为止,再回退并试其他路径。
  • 遍历过的节点会做标记,防止重复访问。
  • 对所有可达节点的访问顺序不确定。
    深度优先遍历的实现步骤:
  1. 初始化栈,将起点入栈。
  2. 当栈不为空时,重复以下操作:
  • 出栈顶节点并访问。
  • 将该节点的所有未访问过的相邻节点入栈。
  • 标记该节点为已访问。
  1. 重复步骤2直到栈为空,算法结束。
    深度优先遍历的时间复杂度也为 O(V+E),空间复杂度为 O(V)。它主要用于拓扑排序、寻找连通分量等。
    广度优先遍历按层次展开地访问节点,而深度优先遍历按路径探索地访问节点。两者各有应用场景。

以最短路径为例子

// 图使用邻接表表示
const graph = {
  'A': ['B','C'],
  'B': ['A','D','E'],
  'C': ['A','F'],
  'D': ['B'],
  'E': ['B','F'],
  'F': ['C','E']
};

// 通过递归实现深度优先遍历
function dfs(curr, end, path, shortest) {
  path.push(curr); // 加入当前节点到路径
  
  if (curr === end) { // 到达终点
    shortest = [...path]; // 更新最短路径
  } else {
    graph[curr].forEach(next => {
      if (path.indexOf(next) === -1) { // 节点未访问过
        dfs(next, end, path, shortest); // 递归
        path.pop(); // 回溯
      }
    });
  }
}

// 寻找最短路径的入口函数  
function findShortestPath(start, end) {
  const path = [];
  let shortest = null;
  
  dfs(start, end, path, shortest);
  
  return shortest;
}

const shortestPath = findShortestPath('A', 'F'); 
console.log(shortestPath); // ['A', 'C', 'F']

两种算法的总结

区别:

  • 广度优先遍历(BFS):从起始节点开始逐层扩展,按照距离从近到远遍历节点,先访问完一层节点再继续下一层。适合用于查找最短路径、连通性检测、拓扑排序等问题。
  • 深度优先遍历(DFS):从起始节点开始沿着一条路径尽可能深入,直到无法继续扩展,然后回溯并探索其他路径。适合用于查找路径、连通性检测、图的遍历等问题。

算法复杂度:

  • 广度优先遍历的时间复杂度为 O(V + E),其中 V 是节点数,E 是边数。空间复杂度为 O(V),因为需要使用队列来保存节点。
  • 深度优先遍历的时间复杂度为 O(V + E),其中 V 是节点数,E 是边数。空间复杂度为 O(V),因为递归调用会使用系统栈来保存调用信息。

广度优先遍历的使用场景和缺陷:

  • 使用场景:查找最短路径、连通性检测、拓扑排序等问题。在带权重或无权重的图中查找最短路径时,广度优先遍历通常是比较直观的选择。
  • 缺陷:当图较大时,广度优先遍历可能需要占用较大的内存空间,特别是在遍历的层数较多的情况下。另外,广度优先遍历在查找所有路径或路径数量较多的情况下效率较低。

深度优先遍历的使用场景和缺陷:

  • 使用场景:查找路径、连通性检测、图的遍历等问题。在回溯和搜索问题时,深度优先遍历通常更为合适。
  • 缺陷:深度优先遍历有可能陷入无限循环,需要使用额外的数据结构(例如哈希表)来记录已访问的节点,避免重复访问。对于非连通图,深度优先遍历可能不会遍历到所有的节点。此外,深度优先遍历不保证找到最短路径,因为它的搜索顺序可能会导致先找到一个较长的路径而非最短路径。

综合比较:
广度优先遍历和深度优先遍历都有各自的优势和适用场景。广度优先遍历在查找最短路径、连通性检测等问题上表现较好,而深度优先遍历在回溯和搜索问题上更加合适。在选择算法时,需要根据具体问题的特点来决定使用哪种遍历方法。有时,两种遍历方法也可以结合使用,例如在查找图中的所有路径时,可以先用深度优先遍历找到所有可能的路径,然后再筛选出最短路径。

【数据结构】图的遍历:广度优先(BFS),深度优先(DFS) 算法思想,广度优先生成树,深度优先生成树,算法实现 阅读详情

相关推荐

算法详解——图的深度优先遍历和广度优先遍历

图数据中的深度优先遍历算法和广度优先遍历算法

python_plus的博客 8331

广度优先遍历(Breath First Search)

前言 深度优先遍历(Depth First Search, 简称 DFS) 与广度优先遍历(Breath First Search)是图论中两种非常重要的算法,生产上广泛用于拓扑排序,寻路(走迷宫),搜索引擎,爬虫等,也频繁出现在 leetcode,高频面试题中。 本文将会从以下几个方面来讲述深度优先遍历相信大家看了肯定会有收获。 深度优先遍历 深度优先遍历简介 习题演练 DFS在搜索引擎中的应用 深度优先遍历简介 广度优先遍历 广度优先遍历,指的是从图的一个未遍历的节点出发,先遍历这个节点的相邻节点,

weixin_44122303的博客 2万+

【数据结构】图的遍历之DFS和BFS

1.图的遍历包括深度优先遍历DFS和广度优先遍历BFS,这两种遍历算法在

淡定从容的专栏 2479

图(graph)的遍历-----广度优先遍历(BFS)

​ 广度优先搜索(Breadth First Search)简称广搜或者 BFS,是遍历图存储结构的一种算法,既适用于无向图(网),也适用于有向图(网)。 广度优先遍历是一种图和树的遍历策略,它的核心思想是从一个起始节点开始,访问其所有邻近节点,然后再按照相同的方式访问这些邻近节点的邻近节点。这种遍历方式类似于波纹在水面上扩散的过程。 ​

m0_73633088的博客 2万+

Starlink vs Kuiper vs OneWeb:三大低轨卫星网络架构对比与实战应用场景解析

本文对比分析了Starlink、Kuiper和OneWeb三大低轨卫星网络架构的技术差异与商业应用场景。从轨道设计、通信性能到商业落地,详细解析了各系统在近地卫星网络领域的独特优势与挑战,为未来全球宽带服务格局提供专业见解。

weixin_29255731的博客 805

【RS】哨兵系列数据下载(哨兵2号Sentinel-2波段介绍、下载)

以哨兵二号为示例,分享如何下载欧空局的哨兵系列数据

Remote Sensing迷途小书童 1万+

图的遍历(广度优先遍历,BFS)

广度优先遍历入栈是按照层次将结点进行先后保存,先出栈的也是层数最小的结点,从而实现了广度优先遍历的按层数先后进行访问的要求。因为广度优先遍历操作中需要队列的基本操作,下面的队列(循环队列)为两种图的广度优先遍历共用的。输出: (结点数据为char类型时要注意输入时的空格和换行符的读取问题)图的遍历操作是从图中某一顶点出发,对图中所有顶点访问一次且仅访问一次。(1)在图中,遍历的起始顶点是编号最小的顶点。,将未被访问的邻接点访问并入栈(内层循环);(2)访问顶点v,顶点v入队列Q;(2)邻接表的广度优先遍历。

m0_63223213的博客 4451

Tribon Vitesse开发教程(一)

Tribon Vitesse简介 Tribon Vitesse是Tribon提供给Python编程语言的编程接口,它是一系列的API。使用Python的语法调用这些API,结合Python语言自身的语法生成的程序叫做Vitesse程序。Vitesse是法语“速度”的意思,读作“为戴斯”。使用Tribon Vitesse可以直接访问Tribon产品信息模型和使用Tribon应用程序的功能,以控制设计

forevermemory的专栏 2587

深度优先遍历和广度优先遍历

一个简单的树结构图: 深度优先遍历 深度优先遍历指的是,从树的根节点开始,先遍历左子树,然后遍历右子树。 我们借助栈结构来实现深度优先遍历。上图的深度优先遍历结果为:ABDECFG 应用场景: 前序遍历、中序遍历、后序遍历 例如《二叉树(#144 前序遍历、#94中序遍历、#145后序遍历)&深度优先遍历》 广度优先遍历 从根节点开始,沿着树的宽度依次遍历树的每个节点。 我们借助队列结构来实现树的广度优先遍历。上图的遍历结果为:ABCDEFG 应用场景: 层序遍历 例如《#102 二叉树的层序遍

m0_45406092的博客 1万+

vfsglobal预约系统登录问题全解析(by quqi99)

本文全面解析VFS Global预约系统登录常见问题,包括IP限制、验证码验证失败及账号自动删除等。提供详细的解决方案,如DNS配置、浏览器设置及邮箱选择建议,帮助用户顺利完成签证预约。特别针对中国用户遇到的IP限制问题,给出了实用技巧。

gamma的博客 1337

保姆级教程:用Qlib和LightGBM从零搭建你的第一个AI量化选股策略(附完整代码)

本文提供了一份详细的教程,教你如何使用Qlib和LightGBM从零搭建AI量化选股策略。教程涵盖了环境配置、数据获取、特征工程、模型训练和策略回测等关键步骤,并附有完整代码和常见问题解决方案,适合量化投资初学者快速上手。

weixin_29191081的博客 443

java-树的遍历

在编程生活中,我们总会遇见树性结构,这几天刚好需要对树形结构操作,就记录下自己的操作方式以及过程。现在假设有一颗这样树,(是不是二叉树都没关系,原理都是一样的) 1.广度优先遍历 英文缩写为BFS即Breadth FirstSearch。其过程检验来说是对每一层节点依次访问,访问完一层进入下一层,而且每个节点只能访问一次。对于上面的例子来说,广度优先遍历的 结果是:A,B,C,D,E,F,G,H,I(假设每层节点从左到右访问)。 先往队列中插入左节点,再插右节点,这样出队就是先左节点后右节点了。 广度优先

m0_53077601的博客 3062

[特殊字符] 从零构建携程/飞猪机票价格爬虫:Python异步抓取与反爬对抗实战

在出行决策、竞品分析、价格预测模型训练等场景中,稳定获取携程(Ctrip)和飞猪(Fliggy)的实时机票价格波动数据是刚需。然而,这两大平台均部署了业界顶尖的反爬体系——包括但不限于:动态请求签名(SignToken设备指纹采集(UACanvasWebGL接口参数加密(X-Sign_abtestcookie混淆)频率限制与 IP 封禁(滑动窗口 + 行为检测)目录前言:为什么需要自建机票价格爬虫?一、技术选型与项目架构1.1 核心技术栈1.2 系统架构图(文字描述)1.3 法律与道德声明。

2201_76125261的博客 336

图的遍历(搜索)算法(深度优先算法DFS和广度优先算法BFS)

从图的某个顶点出发访问遍图中所有顶点,且每个顶点仅被访问一次。(连通图与非连通图)

sinat_41942180的博客 1697

c\c++: Identifiers, modifier, qualifier, specifier, decorator; systemtap

文章目录参考英语含义在c、C++ 参考 c++ 标准 https://blog.youkuaiyun.com/tyronne/article/details/44016621 英语含义 modifier word or phrase that modifies (modify 2) another word or phrase 修饰语. qualifier (grammar) word, esp an adjective or adverb, that qualifies another word 修饰词; (尤指)形

mzhan017的博客 2421

QCC305x-QCC304x系列开发教程之应用程序子系统详解 嵌入式

本文对QCC305x-QCC304x系列芯片的应用程序子系统进行了详细解析,并给出了一个LED闪烁的示例代码。嵌入式系统的开发既需要理论知识的支持,也需要实践经验的积累,希望本文能够为读者在QCC305x-QCC304x系列芯片的开发中提供一些有益的指导。QCC305x-QCC304x系列芯片提供了丰富的外设接口,包括UART、SPI、I2C等,开发者可以根据需求选择适合的接口进行数据传输和控制。QCC305x-QCC304x系列芯片的应用程序子系统是整个嵌入式系统的核心部分,负责管理和执行各种应用程序。

CodeMaven的博客 224

深度优先遍历访问的边集合_图的两种遍历

邻接矩阵和邻接表在讲数据结构的那一节里我们提到了图这种数据结构,并且介绍了两种用来表示图的方法:邻接矩阵和邻接表。接下来我们来分别看看它们是如何表示一张图的吧。对于图而言,节点之间的连接是不受限制的,即一个节点可以连接任意节点(包括自身),并且还具有方向性。所以,我们可以用 0 和 1 两种状态来表示一个节点 是否能够与另一个节点 直接相连。假设一个图由 个节点组成,那么我们就有 种可...

weixin_33443333的博客 816

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

二叉树 深度优先遍历(DFS) + 广度优先遍历(BFS)

深度优先与广度优先

2302_81838100的博客 171

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

大话数据结构(十一)图Graph的遍历

1.深度优先遍历 又称为深度优先搜索,简称为DFS。

苞米地里捉小鸡的博客 194

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

图的邻接表与邻接矩阵的-深度优先搜索(dfs)与广度优先搜索(bfs)

是从图的某一顶点出发,按照某种搜索方式对图中所有顶点访问一次且仅一次。图的遍历可以解决很多搜索问题,在实际中应用非常广泛。图的遍历根据搜索方式的不同,分为广度优先搜索和深度优先搜索。

weixin_64687170的博客 530

图的深度优先遍历与广度优先遍历

图的广度优先遍历 package class06; import java.util.HashSet; import java.util.LinkedList; import java.util.Queue; public class Code01_BFS { public static void bfs(Node node) { if (node == null) { return; } Queue<Node> queue = new LinkedList<&.

好想去看海 125

图:高频面试题-图的广度和深度优先遍历

图的高频面试题-图的广度和深度优先遍历

个人专长:数据结构和算法、大数据、数据库、主流框架 331

图的概念,创建及图的深度优先算法(DFS)及图的广度优先算法(BFS)的代码实现(Java)

1 图的介绍

代码之美 408

深度优先遍历与广度优先遍历(一)

原文站点:https://senitco.github.io/2018/02/18/data-structure-dfs-bfs-1/ 数据结构与算法中深度优先遍历(DFS)与广度优先遍历(BFS)问题总结归纳。 Clone Graph 题目描述:LeetCode Clone an undirected graph. Each node in the graph contains a ...

Zachary_Co的博客 583

Python 树的深度优先和广度优先

""" 广度优先和深度优先 """ # 树的节点,如果是第一个,则为root节点 class Node: def __init__(self, value): self.val = value self.left = None self.right = None # 定义树 class Tree: def __init__(self): self.root = None # 添加元素 def add_el

_Tsun 的博客 760
上一篇: 前端存储之sessionStorage和localStorage
下一篇: 正则表达式、常用的正则
heiyay
博客等级 码龄8年 617粉丝 177原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值