js递归树结构,返回符合条件的子集

JavaScript 递归遍历树结构返回符合条件的子集

下面我将介绍几种在 JavaScript 中递归遍历树结构并返回符合条件的子集的方法。

方法一:使用递归函数返回符合条件的子树

function findSubtree(tree, condition) {
  if (condition(tree)) {
    return tree;
  }

  if (tree.children && tree.children.length) {
    for (let child of tree.children) {
      const result = findSubtree(child, condition);
      if (result) {
        return result;
      }
    }
  }

  return null;
}

// 使用示例
const tree = {
  id: 1,
  name: 'Root',
  children: [
    {
      id: 2,
      name: 'Child 1',
      children: [
        { id: 4, name: 'Grandchild 1', children: [] }
      ]
    },
    {
      id: 3,
      name: 'Child 2',
      children: [
        { id: 5, name: 'Grandchild 2', children: [] }
      ]
    }
  ]
};

const result = findSubtree(tree, node => node.id === 5);
console.log(result); // 输出 { id: 5, name: 'Grandchild 2', children: [] }

方法二:返回所有符合条件的节点数组

function findAllNodes(tree, condition) {
  let results = [];
  
  if (condition(tree)) {
    results.push(tree);
  }

  if (tree.children && tree.children.length) {
    for (let child of tree.children) {
      results = results.concat(findAllNodes(child, condition));
    }
  }

  return results;
}

// 使用示例
const allResults = findAllNodes(tree, node => node.name.includes('Grandchild'));
console.log(allResults); // 输出包含所有Grandchild节点的数组

方法三:返回包含符合条件的节点的子树

function filterTree(tree, condition) {
  // 如果节点本身符合条件,直接返回整个子树
  if (condition(tree)) {
    return tree;
  }

  // 否则处理子节点
  if (tree.children && tree.children.length) {
    const filteredChildren = tree.children
      .map(child => filterTree(child, condition))
      .filter(child => child !== null);

    if (filteredChildren.length) {
      return {
        ...tree,
        children: filteredChildren
      };
    }
  }

  return null;
}

// 使用示例
const filteredTree = filterTree(tree, node => node.id === 5 || node.id === 1);
console.log(filteredTree);

方法四:使用深度优先搜索(DFS)返回路径

function findPath(tree, condition, path = []) {
  path = [...path, tree];
  
  if (condition(tree)) {
    return path;
  }

  if (tree.children && tree.children.length) {
    for (let child of tree.children) {
      const result = findPath(child, condition, path);
      if (result) {
        return result;
      }
    }
  }

  return null;
}

// 使用示例
const path = findPath(tree, node => node.id === 5);
console.log(path); // 输出从根节点到目标节点的路径数组

方法五:使用ES6的reduce实现

const reduceTree = (tree, condition, reducer, accumulator) => {
  accumulator = reducer(accumulator, tree, condition(tree));
  
  if (tree.children && tree.children.length) {
    accumulator = tree.children.reduce(
      (acc, child) => reduceTree(child, condition, reducer, acc),
      accumulator
    );
  }
  
  return accumulator;
};

// 使用示例:收集所有符合条件的节点
const allMatches = reduceTree(
  tree,
  node => node.id > 2,
  (acc, node, isMatch) => isMatch ? [...acc, node] : acc,
  []
);
console.log(allMatches);

注意事项

  1. 确保树结构中有终止条件(如没有子节点时停止递归)
  2. 对于大型树结构,递归可能会导致堆栈溢出,可以考虑使用迭代方式
  3. 根据需求选择合适的方法:只需要第一个匹配项、所有匹配项、还是包含匹配项的子树
  4. 如果树结构可能被修改,考虑使用深拷贝避免副作用

以上方法可以根据实际需求进行调整和组合使用。

你可能感兴趣的:(开发DEMO,javascript,开发语言,ecmascript)