簡體   English   中英

迭代/遞歸

[英]Iterative / Recursion

我已經編寫了有關如何使用for循環查找給定字符串的排列的代碼。 我遵循了教授的偽代碼,但是不知道如何轉換它以便遞歸。 (對於STL算法,goto除外)。

void perms(string prefix, string rest)
{
    //  Followed Format of Pseudocode that Professor gave us
    //  If nothing remains in the rest string cout what we have for prefix
    if (rest == "")
    {
        cout << prefix << endl;
    }
    else
    {
        for (int i = 0; i < rest.length(); i++)
        {
            string prefix2 = prefix + rest[i];
            string rest2 = rest.substr(0, i) + rest.substr(i + 1);
            perms(prefix2, rest2);
        }
    }
}

該代碼運行良好,只需要幫助將其轉換為遞歸即可。

要將循環提升為遞歸,必須將迭代變量i轉換為參數:

第1步:

void printPermutations(string prefix, string rest, int i = 0)

第2步:

void printPermutations(string prefix, string rest, int i = 0)
{
    //  Followed Format of Pseudocode that Professor gave us
    //  If nothing remains in the rest string cout what we have for prefix
    if (rest == "")
    {
        cout << prefix << endl;
    }
    else if (i < rest.length())
    {
       // original loop body
       string prefix2 = prefix + rest[i];
       string rest2 = rest.substr(0, i) + rest.substr(i + 1);

       // true original recursion with different prefix and tail.
       printPermutations(prefix2, rest2);

       // loop continuation via tail recursion: original prefix, next i.
       printPermutations(prefix, rest, i + 1);
    }
}

這幾乎是機械的轉變。 首先,將i初始化為0已進入參數列表,在列表中我們通過默認設置進行了設置(必要時,我們也可以使調用者顯式傳遞零)。 刪除了循環的for循環頭,僅將其替換為循環保護條件,該條件轉換為if條件。 然后,循環的延續僅通過尾部調用來完成,在該調用中我們傳遞i + 1 ,這成為i的下一個值。

可以想象這個中間版本仍然是迭代的:

void printPermutations(string prefix, string rest)
{
    int i = 0;

topOfFunction:

    //  Followed Format of Pseudocode that Professor gave us
    //  If nothing remains in the rest string cout what we have for prefix
    if (rest == "")
    {
        cout << prefix << endl;
    }
    else if (i < rest.length())
    {
       // original loop body
       string prefix2 = prefix + rest[i];
       string rest2 = rest.substr(0, i) + rest.substr(i + 1);

       // true original recursion with different prefix and tail.
       printPermutations(prefix2, rest2);

       // loop continuation via tail recursion: original prefix, next i.
       i = i + 1;
       goto topOfFunction;
    }
}

請注意,盡管rest == ""檢查包含在循環中,但我們知道它保持為false,因為我們從不修改rest

每個循環都可以轉換為遞歸:

void test() {
    int functionVar = 10;
    int sum = 0;
    for (int i=0, int j=2; i<10; i = i - 1, j = j + 2) {
       sum = sum + someFun(i, functionVar);
    }
    // Do something with sum
    cout << sum << endl;
}

可以很容易地這樣重寫:

int forReplacement(int i, int j, int sum, functionVar) {
    if (i < 2) {
      return forReplacement(i - 1, j + 2, sum + someFun(i, functionVar), functionVar);
    }
    return sum;
}

void test() {
    int functionVar = 10;
    int sum = forReplacemenrt(0, 0, 0, functionVar);
    // Do something with sum
    cout << sum << endl;
}

您可以將forReplacement lambda並在其閉包中對其進行引用以使其能夠重復出現,然后functionVarsum可以是閉包變量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM