这是使用递归的正确方法吗?

时间:2011-12-06 00:15:32

标签: c++ recursion

  

给定字符串st递归计算,如果t中包含s,则返回true

     

示例:bool find("Names Richard", "Richard") == true;

我已经编写了下面的代码,但我不确定它是否是在C ++中使用递归的正确方法;我刚刚在课堂上学习了递归。

#include <iostream>

using namespace std;

bool find(string s, string t)
{
    if (s.empty() || t.empty())
        return false;
    int find = static_cast<int>(s.find(t));
    if (find > 0)
        return true;
}

int main()
{
    bool b = find("Mississippi", "sip");
    string s;
    if (b == 1) s = "true";
    else 
        s = "false";
    cout << s;
}

如果有人在我的代码中发现错误,请告诉我,以便我可以修复它或在哪里可以学习/阅读有关此主题的更多信息。我需要为本周三的递归测试做好准备。

4 个答案:

答案 0 :(得分:4)

自从我写完答案后,问题发生了变化。

我的评论是关于看起来像这样的代码(可以递归)......

#include <iostream>

using namespace std;

bool find(string s, string t)
{
    if (s.empty() || t.empty())
        return false;
    string start = s.substr(0, 2);
    if (start == t && find(s.substr(3), t));
        return true;
}

int main()
{
    bool b = find("Mississippi", "sip");
    string s;
    if (b == 1) s = "true";
    else 
        s = "false";
    cout << s;
}

请注意:

if (start == t && find(s.substr(3), t));
    return true;

这不符合你的想法。

;语句末尾的if会留空。无论该测试的结果如何,您的find()函数都将返回true

我建议您在编译之前调高警告级别以捕获此类问题。

顺便说一句,我发现在每个代码块周围使用大括号,甚至是单行块,可以帮助我避免这种错误。

您的代码中还有其他错误。从2中删除幻数3find()将鼓励您思考它们代表的内容并指出正确的道路。

您希望start == t && find(s.substr(3), t)如何运作?如果你能用简单的英语(或你的母语)表达一个算法,你就有更高的机会用C ++表达它。

此外,我建议添加应返回false的测试用例(例如find("satsuma", "onion"))以确保您的代码与应返回true的调用一样有效。

最后一条建议是风格化的,像这样放置你的代码会使你测试的布尔表达式更加明显,而不需要求助于临时并与1进行比较:

int main()
{
    std::string s;
    if (find("Mississippi", "sip"))
    {
        s = "true";
    }
    else
    {
        s = "false";
    }
    std::cout << s << std::endl;
}

祝你上课好运!

答案 1 :(得分:2)

你的递归函数需要两件事:

  1. 失败和成功的明确条件(可能超过1)
  2. 调用自己来处理问题的更简单版本(越来越接近答案)。
  3. 这是一个快速分析:

    bool find(string s, string t)
    {
        if (s.empty() || t.empty())  //definite condition of failure. Good
            return false;
        string start = s.substr(0, 2);
        if (start == t && find(s.substr(3), t)); //mixed up definition of success and recursive call
            return true;
    }
    

    请改为尝试:

    bool find(string s, string t)
    {
        if (s.empty() || t.empty())  //definite condition of failure. Done!
            return false;
        string start = s.substr(0, 2); 
        if (start == t)  //definite condition of success. Done!
            return true;
        else            
            return find(s.substr(3), t) //simply the problem and return whatever it finds
    }
    

答案 2 :(得分:0)

你说的是正确的 - 只要函数调用自己就可以说它是递归的 - 但即使是最简单的测试也应该告诉你代码不能正常工作。例如,将"sip"更改为"sipx",它仍会输出true。你编译并运行这个程序了吗?您是否使用各种不同的输入进行了测试?

答案 3 :(得分:0)

您没有使用递归。在你的函数中使用std::string::find感觉就像作弊(这很可能不会获得积分)。

该任务的唯一合理解释是:在不使用循环或字符串函数的情况下检查t是否为s的中缀。

让我们看一下这个简单的案例:Epsilon(空字)是永远字的中缀,所以如果t.empty()成立,你必须返回true。 否则你有两个选择:

  1. t可能是s的前缀,使用递归检查很简单;只需检查t的第一个字符是否等于s的第一个字符,并使用其余字符串调用isPrefix。如果返回true,则返回true。
  2. 否则,您弹出s的第一个字符(而不是t),然后递归(此时调用find)。
  3. 如果您遵循此配方(如果您问我,使用char const*比使用std::string更容易实现btw。)您将获得仅使用条件而不使用库支持的递归函数。

    注意:在所有最有效的实施中,这是,但您并没有要求提高效率,而是要求递归功能。