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)。
相关推荐
白兰地空瓶4 分钟前
你以为树只是画图?不——它是算法面试的“隐形主角”
前端·javascript·算法
好易学·数据结构14 分钟前
可视化图解算法74:最小花费爬楼梯
数据结构·算法·leetcode·动态规划·力扣
Maỿbe39 分钟前
力扣hot图论部分
算法·leetcode·图论
LYFlied1 小时前
【每日算法】LeetCode 78. 子集
数据结构·算法·leetcode·面试·职场和发展
月明长歌1 小时前
【码道初阶】【Leetcode606】二叉树转字符串:前序遍历 + 括号精简规则,一次递归搞定
java·数据结构·算法·leetcode·二叉树
子枫秋月1 小时前
C++字符串操作与迭代器解析
数据结构·算法
鹿角片ljp1 小时前
力扣234.回文链表-反转后半链表
算法·leetcode·链表
(●—●)橘子……1 小时前
记力扣1471.数组中的k个最强值 练习理解
数据结构·python·学习·算法·leetcode
oioihoii1 小时前
C++共享内存小白入门指南
java·c++·算法
Bruce_kaizy1 小时前
c++图论————图的基本与遍历
c++·算法·图论