Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.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_Arrays_Recursion - Fatal编程技术网

Javascript 堆栈和递归函数

Javascript 堆栈和递归函数,javascript,arrays,recursion,Javascript,Arrays,Recursion,我希望这不是一个重复的问题——尽管我在这方面找不到太多帮助 我正在练习递归函数(我是一个新手),我正在尝试将数组中的每个数字相乘。有点像阶乘。我有这个代码,但结果它只返回未定义的 代码如下: var stack = []; function countDown(int) { stack.push(int); if (int === 1) { return 1; } return countDown(int - 1); } function multiplyE

我希望这不是一个重复的问题——尽管我在这方面找不到太多帮助

我正在练习递归函数(我是一个新手),我正在尝试将数组中的每个数字相乘。有点像阶乘。我有这个代码,但结果它只返回
未定义的

代码如下:

 var stack = [];

function countDown(int) {
  stack.push(int);
  if (int === 1) {  
    return 1;
  }
    return countDown(int - 1);
}

function multiplyEach() {
  // Remove the last value of the stack 
  // and assign it to the variable int
  int = stack.pop();
  x = stack.length;
  // Base case
  if ( x === 0 ) {
    return;
  }
  // Recursive case
  else {
    stack[int - 1] = int * stack[x - 1];
    return multiplyEach(int);
  }
}

// Call the function countDown(7)
countDown(7);
// And then print out the value returned by multiplyEach()
console.log(multiplyEach());
非常感谢您的见解


干杯

我认为主要的问题是multilyach()定义中没有参数,但您试图在函数中使用一个参数调用它

类似这样的工作原理:

var stack = [1, 2, 3, 4, 5, 6, 7];

function multiplyEach(arr) {
  if (arr.length == 0) {
    return 1;
  } else {
    return arr.pop() * multiplyEach(arr);
  }
}
console.log(multiplyEach(stack));

递归函数multiplyEach()中的基本情况返回未定义

这就是你的问题所在

一个简单的解决方案是:

var stack = [];
var multipliedStack = [];

function countDown(int) {
  stack.push(int);
  if (int === 1) {  
    return 1;
  }
    return countDown(int - 1);
}

function multiplyEach() {
  // Remove the last value of the stack 
  // and assign it to the variable int
  int = stack.pop();
  x = stack.length;
  // Base case
  if ( x === 0 ) {
    return multipliedStack.reverse();
  }
  // Recursive case
  else {
    multipliedStack.push(int * stack[x - 1]);
    return multiplyEach(int);
  }
}

// Call the function countDown(7)
countDown(7);
// And then print out the value returned by multiplyEach()
console.log(multiplyEach());
我不完全明白你说的“有点像阶乘”是什么意思?这个函数到底应该做什么

要理解递归,您需要了解什么是递归基本情况,并且我认为您需要修改代码中没有正确使用的push()和pop()


递归函数通常有点混乱,如果您习惯于迭代,请继续尝试,您会很快适应它。

首先要解决的是,从外观上看,multilyeach()函数应该有一个名为int的参数。您正在使用的方法可能更适合于不同的技术,但我们将继续讨论

接下来,在multilyach()中,有两种可能的路径:

  • 堆栈仍然有元素,在这种情况下,我们将堆栈上的新顶部值乘以旧顶部值,然后继续运行另一个multilyach

  • 堆栈是空的,我们只是返回

  • 这里的问题是,我们实际上并没有返回最终的堆栈值,或者将其保留在那里以供以后访问。我们实际上丢失了它,那么函数输出是什么呢

    在许多语言中,我们都会为这个函数定义一个返回类型,或者为无值定义
    void
    ,或者为返回相乘的值定义
    int
    。然而,在Javascript中,没有不返回值的函数;JS中的“nothing”表示为
    未定义
    。当您返回multilyach()时,您正在将它的另一个调用推送到调用堆栈上,并等待实际返回值。。。结果是
    return,JS将其解释为
    返回未定义。同样,在大多数语言中,都会出现某种形式的错误,但在JS中不会!让我们看看两种可能的实现:

  • 您使用的自定义堆栈:

    // your stack is fine, so we'll skip to the meat
    function multiplyEach() {
        var int = stack.pop(), x = stack.length;
        stack[x - 1] *= int;
        if(x < 2) // to multiply, we need at least two numbers left
            return;
        multiplyEach();
    }
    
    //...
    multiplyEach();
    console.log(stack[0]);
    
  • 它们都是递归实现的不同方式;递归本质上要求函数调用自身。另一种可能是让一个参数存储总数,而不是像选项2中那样乘以返回值;这就是所谓的尾部递归


    编辑:注意到选项1的基本案例位于错误的位置,所以我移动了它。它现在应该可以工作了。

    递归地,您可以这样做:

    功能多通道(arr、大小){
    返回大小===0?arr[size]:arr[size]*multiplyEach(arr,size-1);
    }
    var数组=[1,2,3,4,5,6,7,8,9];
    
    log(multiplyEach(array,array.length-1))有时递归更适合解决问题,有时迭代更适合解决问题

    递归更适合于在满足条件之前执行操作,然后退出,类似于while循环

    迭代更适合于执行动作N次,然后退出,类似于for循环

    在本例中,我们希望输入一个数组并输出该数组中所有元素的乘积。换句话说,我们要执行N-1乘法,其中N是数组中的元素数。既然我们知道要执行的操作的数量,我们就应该通过下面的迭代来解决问题

    var arr = [1, 2, 3]
    var result = multiplyEach(arr)
    console.log(result)
    // -> 6
    
    function multiplyEach(arr) {
        var result = 1
        arr.map(function(value) {
            result *= value
        })
        return result
    }     
    
    请记住,上面所说的是一个近似的经验法则,因为有时候递归比迭代更优雅。下面是实阶乘的简单、递归和优雅的实现

    function factorial(value) {
        return 1 === value ? 1 : value * factorial(value - 1)
    }
    
    factorial的迭代实现在while循环形式和for循环形式中都没有那么漂亮

    function factorial(value) {
        var result = 1
        while (value > 0) {
            result *= value
            value--
        }
        return result
    }
    
    function factorial(value) {
        var result = 1
        for (var i = 0; i < value; i++) {
            result *= value
        }
        return result
    }
    
    函数阶乘(值){
    var结果=1
    而(值>0){
    结果*=值
    价值观--
    }
    返回结果
    }
    函数阶乘(值){
    var结果=1
    对于(变量i=0;i
    感谢您的见解!这个实现可能会产生不想要的结果,因为在同一个数组上应用函数两次会产生不同的结果,因为JS对传递给FunctionsHanks的所有对象都使用pass-by-reference,但它在Chrome上工作(当然,不是针对任意大小的数组…)。它不会使用同一数组调用函数两次,因为每次调用函数时,我都会弹出一个元素。对吧?这真的很有帮助!谢谢你抽出时间。这很有帮助!谢谢。首先,不要将全局状态用作
    var堆栈
    。您也不应该使用自己的堆栈结构,除非您必须(查看我的)很好地比较概念。备注:1)
    map
    在引擎盖下以循环或递归方式实现。这意味着
    map
    是循环的抽象,而递归是循环的完全替代(实际上递归比循环更具表现力)2)你的阶乘是幼稚的,因为它不是尾部递归,因此必然会炸毁堆栈。
    function factorial(value) {
        var result = 1
        while (value > 0) {
            result *= value
            value--
        }
        return result
    }
    
    function factorial(value) {
        var result = 1
        for (var i = 0; i < value; i++) {
            result *= value
        }
        return result
    }