简体   繁体   English

JS将递归function转换为蹦床

[英]JS convert recursive function to trampoline

I am struggling to convert the JS recursive function below into aa trampoline function(s) in order to avoid maxing out the call stack with deep nodes.我正在努力将下面的 JS 递归 function 转换为 aa trampoline 函数,以避免使用深节点最大化调用堆栈。

It returns an array of all children nodes from the initial root node passed in. Note, list is a Map used to lookup the children of the current node for the next recursion iteration.它从传入的初始根节点返回一个包含所有子节点的数组。注意,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;
} 

How do I setup the trampoline structure in order to build the array of nodes to return at the end?如何设置蹦床结构以构建节点数组以在最后返回?

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,

As we know that recursion uses memory stack to push and remember the next recursive function calls, so we need something to remember our next function calls.我们知道递归使用 memory 堆栈来推送和记住下一个递归 function 调用,所以我们需要一些东西来记住我们的下一个 ZC1C425268E68385D1AB5074C17A94F14 调用。 Here I'm using nodes array to push child node ids for next execution cycle.在这里,我使用nodes数组来推送子节点 ID 以供下一个执行周期。 On each node id first we check if it exists in the list map.在每个节点 id 上,我们首先检查它是否存在于list map 中。 If yes then push it into results and iterate its children and push child ids in nodes for next cycle.如果是,则将其推送到results中并迭代其子级并将子级 ID 推送到nodes中以进行下一个周期。 Note that I'm checking if a child id has already been processed or not to avoid a cyclic infinite loop.请注意,我正在检查子 ID 是否已被处理,以避免循环无限循环。 And for the current node I'm using index and the break point is the end of nodes .对于当前节点,我使用的是index ,断点是nodes的结尾。 Here's my solution:这是我的解决方案:

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));

Here's the sample code in js: https://ideone.com/Avnq9h这是js中的示例代码: https://ideone.com/Avnq9h

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM