【问题标题】:Heap's Algorithm Walk-Through堆算法演练
【发布时间】:2017-03-28 16:32:32
【问题描述】:

所以,我正在学习递归,并且正在处理一个需要数组中元素的所有变体的编码挑战。

我被指向Heap's algorithm,这就是我到目前为止在 JavaScript 中制定的内容。

function generate(n, array) {
    if (n == 1) {
        return array;
    }
    else {
        for (var i = 0; i < n - 1; i++) {
            generate(n - 1, array);
            if (n % 2 == 0) {
                swap(array[i], array[n - 1]);
            }
            else {
                swap(array[0], array[n - 1]);
            }
        }
        generate(n - 1, array);
    }
}

请忽略我没有将“交换”实例翻译成 JavaScript 的事实。

我有点不确定如何准确地遍历该算法的递归部分

假设我有数组:[A,B,C,D,E]。我相信我将传递给外部函数的参数是:

generate(5, [A,B,C,D,E]);

在这种情况下,n 不等于 1,所以我将继续讨论“else”部分。 我遇到了 for 循环,因为 n 是 5,所以它会执行。

接下来:函数调用自己,但这次的参数是:

generate(4, [A,B,C,D,E]);

我的困惑从这里开始

当我经历这个过程时,我是否继续讨论“if”/“else”条件 还是我(在递归调用之后)回到外部函数的最开始?

更新

以下是 Heap 算法的完全翻译的 JavaScript 版本。

function generate(n, array) {
//console.log("ENTER", n, array)

if (n == 1) {

    console.log(array);
}

else {

    for (var i = 0; i < n - 1; i++) {
        //console.log("RECUR", n-1, array)


        generate(n - 1, array);

        if (n % 2 == 0) {
            //console.log("SWAP ", n, array)

            var one = array[i];
            var two = array[n - 1];

            array[i] = two;

            array[n - 1] = one;

            //swap(array[i], array[n - 1]);
        }

        else {
            //console.log("SWAP ", 0, n-1)

            var first = array[0];
            var second = array[n - 1];

            array[0] = second;

            array[n - 1] = first;


            //swap(array[0], array[n - 1]);
        }
         //console.log("array", array)
    }

    //console.log("RECUR 2", n-1, array)

    generate(n - 1, array);
}

//console.log("LEAVE", n, array)

}

我在纸上遍历它,直到我再次重复 [A,B,C,D]。

认为我搞砸了,我决定实施 Prune 的控制台输出建议,看看控制台中发生了什么,这很有帮助。

修复了一个小错误后,现在可以正常工作了。

感谢所有提供帮助的人!

【问题讨论】:

  • 当你调用的函数返回一个值时,你继续前进,你不会从头开始。
  • @vic3685 - 我猜我将无法继续执行 for 循环中的“if”语句,直到 generate(n - 1, array) 为:generate (2 - 1, array),因为那是它会返回一些东西 (1)....

标签: javascript algorithm recursion heaps-algorithm


【解决方案1】:

在这一点上,我的典型答案是,如果您在纸上演算法时遇到困难,不要!让电脑替你做。插入一堆 console.log 命令来跟踪执行。跟踪每个例程和调用的进入和退出,包括有用的值。

function generate(n, array) {
    console.log("ENTER", n, array)
    if (n == 1) {
        return array;
    }
    else {
        for (var i = 0; i < n - 1; i++) {
            console.log("RECUR", n-1, array)
            generate(n - 1, array);
            if (n % 2 !== 0) {
                console.log("SWAP ", n, array)
                swap(array[i], array[n - 1]);
            }
            else {
                console.log("SWAP ", 0, n-1)
                swap(array[0], array[n - 1]);
            }
            console.log("array", array)
        }
        console.log("RECUR 2", n-1, array)
        generate(n - 1, array);
    }
    console.log("LEAVE", n, array)
}

这会给你一个可爱的执行跟踪。为了提高可读性,将输出的每一行缩进 2*(5-n) 个空格。

【讨论】:

  • 您需要正确实现swap 以使其有用
  • @Prune - 我在帖子中添加了更新,非常感谢您对此的看法,谢谢!
  • 诸如什么的想法?这是一个非常开放的评论。
【解决方案2】:

让我列举一下你的台词,以便我们更容易地参考它们(见下文)

您从generate(5, [A,B,C,D,E]); 走到generate(4, [A,B,C,D,E]);(在第 7 行),然后您第二次输入generate,但尚未完成第一次通话,因此您将暂停到第一次通话并开始步行第二个

现在(第 2 次呼叫)n=4,所以您再次到达第 7 行,但这次第 3 次呼叫 generate(3, [A,B,C,D,E]) 开始(没有完成之前的呼叫)

第 4 次通话 generate(2, ...) 和第 5 次通话 generate(1, ...) 也是如此,这时情况开始发生变化

在第 5 次调用 n=1 中,因此第 2 行的条件 eval 为 true 并返回 array,我们又回到了我们原来的位置,即第 7 行的第 4 次调用,返回的数组使什么都没有(它没有被分配或任何东西)然后我们到达第 8 行(第一次),而在第 4 次调用中,n=2 因此第二个swaphappends 和i 递增,然后回到第 7 行我们调用再次generate(1, ...) 获得相同的结果......等等

01. function generate(n, array) {
02.     if (n == 1) {
03.         return array;
04.     }
05.     else {
06.         for (var i = 0; i < n - 1; i++) {
07.             generate(n - 1, array);
08.             if (n % 2 !== 0) {
09.                 swap(array[i], array[n - 1]);
10.             }
11.            else {
12.                swap(array[0], array[n - 1]);
13.            }
14.        }
15.        generate(n - 1, array);
16.    }
17. }

【讨论】:

  • 谢谢,这证实了我的怀疑。我要去尝试走过这个。虽然我会使用 A,B,C,D,因为它的排列较少。
  • 很高兴听到。顺便说一句,如果您正在学习递归,我不建议将排列作为第一课。最好尝试一些阶乘、斐波那契或迷宫。 Google 搜索“阶乘递归 javascript”、“斐波那契递归 javascript”和/或“2d 迷宫递归 javascript”
  • 谢谢。实际上,我已经浏览了阶乘和斐波那契示例,并迅速转向这一点,因为我正在做的编码挑战/任务需要它。不过谢谢,我去看看二维迷宫。
猜你喜欢
  • 2017-07-25
  • 2021-02-04
  • 1970-01-01
  • 1970-01-01
  • 2012-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多