如何在js中将递归方法更改为非递归方法

时间:2015-02-23 16:12:26

标签: javascript jquery recursion tree

我写了一个小代码来加载来自GitHub的关注者树。

它适用于我的递归版本,但我无法得到我的" stack-que"版本运行。

我完成循环后收到响应,这是问题;我的递归解决方案使用相同的loadFollowers方法,但由于其调用结构,它会生成所需的树。

我应该以某种方式在通话中关闭异步吗?

function loadFollowers(user,field,callback){
  path = 'https://api.github.com/users/'+user.info[field]+'/followers';
  path += '?client_id=' + pass.client_id + '&client_secret='+pass.client_secret

  console.log("path:"+path+' field: '+field+' node: '+user);

  $.get(path,function(followers){
    for(var i = 0;i < followers.length; i++){ 
      current = new Node();
      current.info = followers[i];
      user.addFollower(current);
      callback();
    };
  });
}

function loadNetworkNonROld(node,depth,field){
var toVisit = [];
var visited =[];
var deep;
var current;
var curr;

  toVisit.push([node,depth]); // saves [node,level] to control how deep it is 
                              // starts at initial node

  while (toVisit.length > 0){   
      curr = toVisit.shift();
      current = curr[0];
      deep = curr[1];
      if((visited.indexOf(current.info[field])===-1) && (deep > 0)){
        visited.push(current.info[field]);
        loadFollowers(current,field,function(){ 
            for(var i=0;i < current.followers.length; i++){
              toVisit.push([current.followers[i],deep-1]);
            }
        });
      }  
  }
  return visited;  
}

运行良好的递归版本如下:

function loadNetwork(node,depth,field){

  loadFollowers(node,field,function(){
  if (depth == 0){return;}
  for(var i=0; i < node.followers.length; i++){
    current = node.followers[i];
    id = current.info[field];
    if (networkAllUsers.indexOf(id)===-1)
    { 
      networkAllUsers.push(id);
      console.log(id);
      loadNetwork(current,depth-1,field);
    }  
  }});
}

github链接是:https://github.com/marcinwal/myownnode.git 并且代码在public / javascript / main.js文件中。

1 个答案:

答案 0 :(得分:0)

看起来问题可能就是迭代版本中loadFollowers的异步运行。

然而,您的问题的关键问题是,当您向我们展示代码时,您不会向我们展示您遇到的错误,而且您不会说出什么是“堆叠”问题&#39 ;是或要求澄清的评论。

此外,您没有向我们提供有关如何运行代码以复制遇到的问题的说明。检查你的代码我做了一系列的猜测,你可以在这个屏幕截图中看到一些结果:

screen shot of trying to replicate the error

我正确地缩进了您的迭代代码,并添加了一些生成上述输出的部分日志记录:

function loadNetworkNonROld(node,depth,field){
  var toVisit = [];
  var visited =[];
  var deep;
  var current;
  var curr;

  toVisit.push([node,depth]); // saves [node,level] to control how deep it is 
                              // starts at initial node

  while (toVisit.length > 0){  
      console.log(toVisit) 
      curr = toVisit.shift();
      current = curr[0];
      deep = curr[1];
      if((visited.indexOf(current.info[field])===-1) && (deep > 0)){
        visited.push(current.info[field]);
        console.log(visited) 
        loadFollowers(current,field,function(){ 
          for(var i=0;i < current.followers.length; i++){
            toVisit.push([current.followers[i],deep-1]);
            console.log('loadFollowers:' + toVisit) 
          }
        });
      }  
  }
  return visited;  
}

现在我可以花更多的精力来解决你的代码,猜测是否有我们得到的输出,你有什么,但你不能让人们很容易帮助。

从我在控制台日志中看到的情况来看,我看起来就像你在深度为1的情况下推动所有节点一样,它们永远不会达到深度0,所以它只是永远地运行。而在递归版本中,深度变为0。

我修改了你的代码:

  while (toVisit.length > 0){  
      console.log(toVisit) 
      curr = toVisit.shift();
      current = curr[0];
      deep = curr[1];
      if((visited.indexOf(current.info[field])===-1) && (deep > 0)){
        visited.push(current.info[field]);
        console.log('loadNetworkNonROld: '+deep);
        loadFollowers(current,field,deep,function(depth){ 
          console.log('loadFollowers:' + (depth-1));
          for(var i=0;i < current.followers.length; i++){
            toVisit.push([current.followers[i],(depth-1)]);
          }
        });
      }  
  }
  console.log('loadNetworkNonROld: visited:'+JSON.stringify(visited));
  return visited;  
}

对loadFollowers函数进行并行更改,以便实际传递深度值。现在代码运行时不会永远迭代,但javascript的异步性质意味着在任何网络调用完成之前返回结果 - 因此访问结果只是第一个用户。