簡體   English   中英

在 c++ 中創建遞歸

[英]Creating a recursion in c++

我正在學習如何編寫遞歸,我對如何將 function 的主體簡化為遞歸感到困惑。

對於我目前的任務,我必須“通過交替的字符來對兩個字符串進行網格划分。如果一個字符串在另一個之前用完,只需從較長的那個中挑選。例如,mesh("Fred", "Wilma") 是 "FWrieldma “。使用遞歸。不要使用循環。”

嗯......我創建了循環......

string result;
for (int i = 0; i < a.size(); ++i)
{
    result += a.at(i) + b.at(i)
}

但是把它變成一個遞歸讓我很難過。

這是我到目前為止所擁有的(我們不允許在標記的位置上方或下方更改任何內容):

#include <string>
using namespace std;

/**
   Combines alternate characters from each string.
   @param a the first string.
   @param b the second string
*/
string mesh(string a, string b)
{
// INSERT CODE BENEATH HERE
     string result;
     if (a.size() < 1) result = b;
     if (b.size() < 1) result = a;
     else
     {
        result = a.at(0) + b.at(1);
     }
return result;
// ENTER CODE ABOVE HERE
}

但我知道這是不對的,因為沒有遞歸而且它完全不起作用

我認為這可以滿足您的要求,並保持 function 原型完好無損。 它看起來也類似於您建議的代碼。

#include <iostream>

using namespace std;

string mesh(string a, string b) {
    if (!a.size()) return b;
    if (!b.size()) return a;
    return a[0] + (b[0] + mesh(a.substr(1), b.substr(1)));
}

int main(int argc, char const *argv[])
{
    printf("%s\n", mesh("Fred", "Wilma").c_str());
    return 0;
}

首先嘗試找出遞歸的單步。 有不止一種方法可以做到這一點,一種可能性是通過使用一些索引pos遍歷字符串,並在一個步驟中從字符串的各個位置添加字符:

std::string mesh(const std::string& a, const std::string& b,size_t pos) {

    /*...*/

    std::string result;
    if (pos < a.size()) result += a[pos];
    if (pos < b.size()) result += b[pos];

    /*...*/
}

為了遞歸,我們再次為下一個索引和 append 調用該方法以得到結果:

std::string mesh(const std::string& a, const std::string& b,size_t pos = 0) {

    /*...*/
    
    std::string result;
    if (pos < a.size()) result += a[pos];
    if (pos < b.size()) result += b[pos];

    return result + mesh(a,b,pos+1);
}

最后我們需要一個停止條件。 當兩個字符串在索引pos處沒有更多字符時,遞歸應該停止:

std::string mesh(const std::string& a, const std::string& b,size_t pos = 0) {

    if (pos >= a.size() && pos >= b.size()) return "";
    
    std::string result;
    if (pos < a.size()) result += a[pos];
    if (pos < b.size()) result += b[pos];

    return result + mesh(a,b,pos+1);
}

例如:

int main() {
    std::cout << mesh("Fred","Wilma");
}

將產生所需的FWrieldma output。

免責聲明:正如 SergeyA 所指出的,我在寫這個答案時並沒有過多關注性能。 我想這是一個練習遞歸的練習,而實際上我看不出有理由通過遞歸來實現它。

只需添加到 large_prime_is_463035 的答案。 如果您必須保持mesh的簽名相同,那么您將創建另一個具有實際實現的 function,現在mesh只能被稱為兩個字符串 arguments。

#include <string>
#include <iostream>
using namespace std;

/**
   Combines alternate characters from each string.
   @param a the first string.
   @param b the second string
*/

void meshInternal(const string a, const string b, string& result, unsigned int index=0){
    if(index >= a.size()){
        result += b.substr(index);
        return;
    }
    if(index >= b.size()){
        result += a.substr(index);
        return;
    }

    result.push_back(a[index]);
    result.push_back(b[index]);
    meshInternal(a, b, result, ++index);
}

string mesh(const string a, const string b)
{
    string result = "";
    meshInternal("Fred", "Wilma", result);
    return result;
}

int main() {
    string result = mesh("Fred", "Wilma");
    std::cout << result << std::endl;
    return 2;
}

由於不可能在mesh function 中傳遞另一個參數,但在每個遞歸調用中,我們需要知道string astring b中的哪個字符將附加到結果中。 一個簡單的解決方案可能是從string astring b中刪除第一個字符,並將 append 刪除到結果中。 現在,當我們傳遞string astring b作為引用時,刪除第一個字符最終會在一段時間后使字符串為空。 因此,我們可以檢查string astring b是否都為空,並將其設置為遞歸調用的基本情況。

這段代碼解決了這個問題:

std::string mesh(string& a, string& b) {

    if (a.size() == 0 && b.size() == 0) return "";
    
    std::string result;
    if (a.size()) {
        result += a[0];
        a.erase(0, 1);
    }
    if (b.size()) {
        result += b[0];
        b.erase(0, 1);
    }

    return result + mesh(a,b);
}

int main()
{
    string a = "Fred";
    string b = "Wilma";
    std::cout << mesh(a,b);

    return 0;
}
#include <string>
#include <iostream>
#include <string_view>

// recursive mesh function.
// passing the result object for effeciency.
void mesh(std::string& result, std::string_view l, std::string_view r)
{
    // check the exit condition.
    // If either the left of right are empty add the other to the result.
    if (std::begin(l) == std::end(l)) {
        result += r;
        return;
    }
    if (std::begin(r) == std::end(r)) {
        result += l;
        return;
    }

    // Add letter from the left and right to the result.
    result += *std::begin(l);
    result += *std::begin(r);

    // Adjust the size of the view
    l.remove_prefix(1);
    r.remove_prefix(1);

    // recursively call to get the next letter.
    mesh(result, l, r);
}

// Utility wrapper to get view of strings and create
// the result object to be passed to the recursive function.
std::string mesh(std::string const& l, std::string const& r)
{
    std::string result;
    mesh(result, std::string_view(l), std::string_view(r));
    return result;
}

int main()
{
    std::cout << mesh("Fred", "Wilma");
}

暫無
暫無

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

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