Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/415.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 返回函数调用与在递归期间仅再次调用函数有什么区别?_Javascript_Algorithm_Recursion_Return_Depth First Search - Fatal编程技术网

Javascript 返回函数调用与在递归期间仅再次调用函数有什么区别?

Javascript 返回函数调用与在递归期间仅再次调用函数有什么区别?,javascript,algorithm,recursion,return,depth-first-search,Javascript,Algorithm,Recursion,Return,Depth First Search,我正在尝试实现DFS,但我不理解在其内部调用函数(递归)和返回函数调用(也是递归?)之间的区别 代码片段1:返回函数调用(回答错误) 在这种情况下,代码没有正确回溯 const图={ 1: [2, 3], 2: [4, 5], 3: [1], 4: [2, 6], 5: [2, 6], 6: [4, 5] } 让我们访问=[]; 常量dfs=(节点)=>{ if(已访问。包括(节点)) 返回; console.log(节点); 访问推送(节点); for(设i=0;i[ 节点, …(图形[节点

我正在尝试实现DFS,但我不理解在其内部调用函数(递归)和返回函数调用(也是递归?)之间的区别
代码片段1:返回函数调用(回答错误)
在这种情况下,代码没有正确回溯

const图={
1: [2, 3],
2: [4, 5],
3: [1],
4: [2, 6],
5: [2, 6],
6: [4, 5]
}
让我们访问=[];
常量dfs=(节点)=>{
if(已访问。包括(节点))
返回;
console.log(节点);
访问推送(节点);
for(设i=0;i当您返回“函数调用”时,实际上是返回被调用函数产生的值。当您只是递归调用一个函数而不返回它时,您不会对返回值做任何事情。它们都是递归的情况,当不在循环中时,它们的工作方式类似


在本例中,由于您正在for循环中使用函数的返回值,因此一旦
dfs(graph[node][i])
第一次运行,并且函数通过返回值完成执行(或者像在本例中一样刚刚完成执行)并退出堆栈调用,for循环结束,函数执行也会停止。

在编程术语中,递归函数可以定义为直接或间接调用自身的例程。因此在您的示例中,这两种函数都被视为递归

但是,当考虑到递归原理是基于这样一个事实,即一个更大的问题是通过重复使用子集问题的解来解决的,那么我们将需要这些子集结果来计算大的结果。如果没有这种回报,你只会得到一个未定义的结果,这无助于你解决问题

一个非常简单的例子是阶乘,其中
fact(n)=n*fact(n-1)

正如您在本例中看到的,事实(4)=4*fact(3),如果没有返回,它将是未定义的


注意:在您的示例中,不调用返回可能会起作用,因为我们没有重新使用子集的结果

如果您编写避免改变外部状态的函数,而是对提供的参数进行操作,那么您会遇到更少的麻烦。下面我们用三个参数编写了
dfs

  • t
    -输入树或图形
  • i
    -开始遍历的id
  • s
    -访问的节点集默认为
    新集
  • 函数*dfs(t,i,s=新集合)
    {如果(s.has(i))返回
    s、 加(i)
    产量一
    对于(t[i]??[]的常数v)
    收益率*dfs(t、v、s)
    }
    常数图=
    { 1: [2, 3]
    , 2: [4, 5]
    , 3: [1]
    , 4: [2, 6]
    , 5: [2, 6]
    , 6: [4, 5]
    }
    for(dfs的常量节点(图1))
    
    console.log(node)
    其他人已经解释了为什么
    return
    会使您的进程短路

    但我认为主要的问题是,您并没有真正使用递归函数返回任何内容,而只是依赖于函数内部的副作用(打印到控制台)。若您真的想要遍历图形,那个么编写一个返回有序节点集合的函数会更简洁。Thankyou的答案提供了一个这样的函数,使用生成器函数,以及一些有价值的建议

    下面是另一种方法,它将(连接的)图形转换为数组:

    const dft=(图形、节点、已访问=新集合([node])=>[
    节点,
    …(图形[节点]).flatMap(
    (n) =>visited.has(n)?[]:dft(图,n,visited.add(n))
    )),
    ]
    常量图={1:[2,3],2:[4,5],3:[1],4:[2,6],5:[2,6],6:[4,5]}
    
    console.log(dft(graph,1))/~>[1,2,4,6,5,3]
    您能解释一下为什么一个返回DFS的正确结果而另一个不返回吗?@HarshaLimaye当您从for循环中返回时,您会提前停止循环(当您退出函数返回调用方时),在第二个示例中,您不会返回,因此,您可以在循环调用
    dfs()
    之后继续循环,这样如果我使用return语句正确,我的“循环”只运行一次?@HarshaLimaye是的,正确。在这种情况下,您可以使用
    forEach()
    方法
    forEach()
    不会使用return语句中断循环。如果它对你有用的话,快告诉我。我写的是一个非生成器方法,它的工作原理类似。类似于
    const dfs=(t,i,s=新集合([i])=>[i,…(t[i].flatMap((n)=>s.has(n)?[]:dfs(t,n,s.add(n))))]
    。你仍然应该发布它!有些初学者很难使用生成器,所以看到其他方法会很有好处:DThanks,post!有趣的是,我经常写类似于dfs的
    dfs
    的东西,以至于有时我忘记了它确切地指的是什么^ ^ ^@Thankyou:我相信这也是一个主要用于树的术语,而不是任意(双)图。它只能访问节点的子集。(例如,尝试从
    6
    开始的任何一种解决方案。它只会产生
    [6,4,2,5]
    )。
    function fact (n) {
     if (n===0 || n===1) return 1;
     else return n*fact(n-1);
    }