【问题标题】:JS convert recursive function to trampolineJS将递归函数转换为蹦床
【发布时间】:2021-06-01 14:37:10
【问题描述】:

我正在努力将下面的 JS 递归函数转换为蹦床函数,以避免用深节点最大化调用堆栈。

它从传入的初始根节点返回一个包含所有子节点的数组。注意,list 是一个 Map,用于查找当前节点的子节点以进行下一次递归迭代。

const getRootSet = (nodeId, list) => {    
  let results = [];
  const node = list.get(nodeId);

  if (node && node.children.size > 0) {       
    results.push(node.nodeId);
    node.children.forEach((value, key) => {
        results = results.concat(getRootSet(list.get(key).nodeId, list) );
    });
  }

  if(node && node.children.size === 0)
  {
    //add last child node
    results.push(node.nodeId);
  }
  return results;
} 

如何设置蹦床结构以构建节点数组以在最后返回?

Sample data:
child, parent,
111111, 222222,
000000, 111111,
060270, 964240,
041342, 964240,
024367, 964240,
052643, 964240,
083020, 060270,
024367, 961758,
024367, 964264,
060270, 024367,
060270, 964240,
123456, 789100,
345678, 789100,

【问题讨论】:

    标签: javascript node.js recursion trampolines


    【解决方案1】:

    我们知道递归使用内存堆栈来推送和记住下一个递归函数调用,所以我们需要一些东西来记住我们的下一个函数调用。在这里,我使用 nodes 数组来推送子节点 ID 以用于下一个执行周期。在每个节点 ID 上,我们首先检查它是否存在于 list 映射中。如果是,则将其推入results 并迭代其子代并将子代ID 推入nodes 以进行下一个周期。请注意,我正在检查子 ID 是否已被处理,以避免循环无限循环。对于当前节点,我使用的是index,断点是nodes 的结尾。这是我的解决方案:

    const getRootSet = (rootNodeId, list) => {    
       let results = [];
       let nodes = [rootNodeId];
       let index = 0;
       while(index < nodes.length) {
         const node = list.get(nodes[index]);
         if(node) {
           results.push(node.nodeId);
           if (node.children.size > 0) {
             node.children.forEach((val, childId) => {
                if(!nodes.includes(childId)) {
                  nodes.push(childId);
                }
             });
           }
         }
         index++;
       }
          
      return results;
    };
    
    console.log(getRootSet('root', list));
    

    这里是js中的示例代码:https://ideone.com/Avnq9h

    【讨论】:

    • 给我一点时间解释一下
    • 由于我不知道list 的正确结构,因此代码可能会在行list.get()node.children.size 上显示一些错误,因为它们取决于list 映射所以你需要相应地更新它们。
    • 太棒了!为了使上面的代码正常工作,我不得不做一个小调整。由于节点的子节点是一个 Map,我必须在 forEach 循环中传递一个值和键,即使我只需要键。否则它会将 undefined 推送到节点数组。 node.children.forEach((val,childId) => { if(!nodes.includes(childId)) { nodes.push(childId); } });
    • 是的,我明白了。我知道这个 node.children 可能会导致问题,但现在很好:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-02
    • 2016-03-24
    • 1970-01-01
    • 2011-12-27
    • 1970-01-01
    • 1970-01-01
    • 2016-01-06
    相关资源
    最近更新 更多