DOM树的深度与广度优先遍历

问题描述

给定一个DOM节点的根元素,请分别实现它的深度优先遍历(DFS)和广度优先遍历(BFS),并返回所有节点名称的数组。

前端意义:这是理解虚拟DOM实现、DOM Diff算法以及任何需要递归操作DOM结构(如UI框架、爬虫、自动化测试)的基础。

解题思路

  1. 深度优先遍历 (DFS)

    • 从根节点开始,尽可能深地访问每个分支。

    • 通常采用递归栈(Stack) 的思想实现。

    • 顺序:A -> B -> D -> E -> C -> F

      text

      复制下载

      css 复制代码
          A
         / \
        B   C
       / \   \
      D   E   F
  2. 广度优先遍历 (BFS)

    • 从根节点开始,一层一层地访问。
    • 通常采用队列(Queue) 的思想实现。
    • 顺序:A -> B -> C -> D -> E -> F

代码实现

scss 复制代码
// 假设我们有一个DOM节点,它有一个`children`属性,包含其所有子元素。

/**
 * 深度优先遍历 - 递归版 (最简洁)
 */
function dfsTraversalRecursive(node) {
  const result = [];
  
  function traverse(node) {
    if (!node) return;
    result.push(node.nodeName); // 访问节点
    // 遍历所有子节点
    for (const child of node.children) {
      traverse(child); // 递归遍历子树
    }
  }
  
  traverse(node);
  return result;
}

/**
 * 深度优先遍历 - 迭代版 (利用栈)
 * 更接近计算机底层实现,避免递归栈溢出风险
 */
function dfsTraversalIterative(root) {
  const result = [];
  const stack = [root]; // 初始化栈,放入根节点

  while (stack.length > 0) {
    const currentNode = stack.pop(); // 弹出栈顶节点
    result.push(currentNode.nodeName); // 访问它

    // 注意:由于栈是"后进先出",我们需要将子节点**逆序**入栈
    // 这样才能保证下一个要处理的是第一个子节点,而不是最后一个
    for (let i = currentNode.children.length - 1; i >= 0; i--) {
      stack.push(currentNode.children[i]);
    }
  }

  return result;
}

/**
 * 广度优先遍历 - 迭代版 (利用队列)
 */
function bfsTraversal(root) {
  const result = [];
  const queue = [root]; // 初始化队列,放入根节点

  while (queue.length > 0) {
    const currentNode = queue.shift(); // 从队列头部取出节点
    result.push(currentNode.nodeName); // 访问它

    // 将当前节点的所有子节点**按顺序**加入队列尾部
    for (const child of currentNode.children) {
      queue.push(child);
    }
  }

  return result;
}

// 示例用法
// const rootElement = document.getElementById('root');
// console.log('DFS Recursive:', dfsTraversalRecursive(rootElement));
// console.log('DFS Iterative:', dfsTraversalIterative(rootElement));
// console.log('BFS:', bfsTraversal(rootElement));

复杂度分析

  • 时间复杂度:O(n)。所有算法都恰好访问每个节点一次。
  • 空间复杂度:O(n)。在最坏情况下(树退化为链表),递归DFS和栈迭代DFS的空间复杂度为O(n)。BFS的空间复杂度取决于每一层的宽度,在最坏情况下(平衡二叉树)也是O(n)。
相关推荐
Fr2ed0m35 分钟前
卡尔曼滤波算法原理详解:核心公式、C 语言代码实现及电机控制 / 目标追踪应用
c语言·人工智能·算法
Sapphire~41 分钟前
重学JS-012 --- JavaScript算法与数据结构(十二)正则表达式
javascript·数据结构·算法
一念&1 小时前
每日一个C语言知识:C 错误处理
c语言·开发语言·算法
丁浩6663 小时前
统计学---2.描述性统计-参数估计
人工智能·算法
sali-tec3 小时前
C# 基于halcon的视觉工作流-章54-N点标定
开发语言·图像处理·算法·计算机视觉·c#
娇娇yyyyyy3 小时前
C++11新特性基础知识点汇总
开发语言·c++·算法
不知名。。。。。。。。4 小时前
算法———栈
算法
烟花落o4 小时前
指针深入第二弹--字符指针、数组指针、函数指针、函数指针数组、转移表的理解加运用
c语言·开发语言·笔记·vscode·算法