堆的算法演练

时间:2016-11-14 22:27:14

标签: javascript algorithm recursion

所以,我正在学习递归,而我正在编写一个编码挑战,需要数组中所有元素的变化。

我被指向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);
    }
}

请忽略我没有将“swap”实例转换为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的控制台输出建议,看看控制台发生了什么,这很有帮助。

修正一个小错误之后,现在工作正常。

感谢所有帮助过的人!

2 个答案:

答案 0 :(得分:3)

此时我的规范答案是,如果您在纸上查看算法时遇到问题,不要!让电脑为你做。插入一堆 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)空格。

答案 1 :(得分:1)

让我列举你的行,这样我们就可以更容易地引用它们了(见下文)

你从while (rs.next()) { String value = rs.getString("COLUMN_NAME"); log.info("COLUMN_NAME:"+value) } 走到generate(5, [A,B,C,D,E]);(第7行),然后第2次输入generate(4, [A,B,C,D,E]);,没有完成第一次通话,所以你暂停了第一次通话并开始与第二次通话

现在(第二个电话)generate所以你再次进入第7行,但这次第3次电话n=4开始(没有完成之前的电话)

同样适用于第4个电话generate(3, [A,B,C,D,E])和第5个电话generate(2, ...),这是事情开始发生变化的时候

在第5个电话generate(1, ...),所以第2行的条件退出为真,并返回n=1,我们回到我们来自的地方,即第7行的第4个电话,其中什么都没有(它没有分配或任何东西)然后我们到达第8行(第一次),而在第4次调用中,array因此第二次n=2发生了swap增加,然后回到第7行,我们再次调用i获得相同的结果......依此类推

generate(1, ...)