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)。
相关推荐
bug_kada2 小时前
面试官:如何解析URL参数?
算法
PineappleCoder2 小时前
面试官你好,请您听我“编解”!!!
前端·算法·面试
我想吃烤肉肉2 小时前
leetcode-python-2154将找到的值乘以 2
python·算法·leetcode
范纹杉想快点毕业2 小时前
请创建一个视觉精美、交互流畅的进阶版贪吃蛇游戏
数据库·嵌入式硬件·算法·mongodb·游戏·fpga开发·交互
先知后行。2 小时前
线程的创建.销毁
开发语言·c++·算法
鱼嘻2 小时前
西嘎嘎学习 - C++ 继承 - Day 10
开发语言·c++·学习·算法
孤廖2 小时前
从 “模板” 到 “场景”,用 C++ 磨透拓扑排序的实战逻辑
开发语言·c++·程序人生·算法·贪心算法·动态规划·学习方法
Flash.kkl3 小时前
优先算法——专题十一:字符串
算法
汉克老师9 小时前
第十四届蓝桥杯青少组C++选拔赛[2023.2.12]第二部分编程题(5、机甲战士)
c++·算法·蓝桥杯·01背包·蓝桥杯c++·c++蓝桥杯