繁体   English   中英

编写一个递归函数来反转输入字符串

[英]Write a recursive function that reverses the input string

我一直在阅读 C++ For Everyone 一书,其中一个练习说要编写一个函数string reverse(string str) ,其中返回值是str的反向。

有人可以写一些基本的代码并向我解释吗? 我从昨天开始就一直盯着这个问题,想不通。 我得到的最远的是让函数返回str的第一个字母(我仍然不知道它是怎么发生的)

这是我得到的(发布这个问题一个小时后):

string reverse(string str)
{
    string word = "";

    if (str.length() <= 1)
    {
        return str;
    }
    else
    {
        string str_copy = str;
        int n = str_copy.length() - 1;
        string last_letter = str_copy.substr(n, 1);

        str_copy = str_copy.substr(0, n);
        word += reverse(str_copy);
        return str_copy;
    }
    return word;
}

如果我输入“Wolf”,它会返回 Wol。 有人帮我在这里如果我return word而不是return str_copy那么我得到一个w如果我return last_letter那么我得到一个l

相反,我将解释递归算法本身。 以应该产生“tupni”的“输入”为例。 您可以通过递归反转字符串

  • 如果字符串为空或单个字符,则原样返回。
  • 除此以外,
    1. 删除第一个字符。
    2. 反转剩余的字符串。
    3. 将上面的第一个字符添加到反转字符串中。
    4. 返回新字符串。

试试这个

string reverse(string &s)
{
    if( s.length() == 0 )  // end condtion to stop recursion
        return "";

    string last(1,s[s.length()-1]);  // create string with last character
    string reversed = reverse(s.substr(0,s.length()-1));
    return last+reversed; // Make he last character first
}

递归函数必须具有以下属性

  • 它必须再次调用自己
  • 当递归结束时,它必须有一个条件。 否则你有一个函数会导致堆栈溢出。

这个递归函数基本上创建了一个包含最后一个字符的字符串,然后用字符串的其余部分(不包括最后一个字符)再次调用自己。 真正的切换发生在返回 last+reversed 的最后一行。 如果情况相反,则什么都不会发生。

这是非常低效的,但它可以展示这个概念。

只是建议一种更好的处理递归的方法:

在 C++ 中使用递归进行字符串反转:

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

string reverseStringRecursively(string str){
    if (str.length() == 1) {
        return str;
    }else{
        return reverseStringRecursively(str.substr(1,str.length())) + str.at(0);
    }
}

int main()
{
    string str;
    cout<<"Enter the string to reverse : ";
    cin>>str;

    cout<<"The reversed string is : "<<reverseStringRecursively(str);
    return 0;
}

这是我的递归函数版本,用于反转输入字符串:

void reverse(char *s, size_t len)
{
    if ( len <= 1 || !s )
    {
        return;
    }
    std::swap(s[0], s[len-1]);// swap first and last simbols
    s++; // move pointer to the following char
    reverse(s, len-2); // shorten len of string
}

我不会为你写一个完整的算法,但这里有一个提示:

如何交换最外面的两个字符,然后将相同的应用于中间的字符?

哦,如果那本书真的提出了string reverse(string str)作为合适的函数签名,那就扔掉它,买一本好书吧

最短和最简单

class Solution {
public:
    string reverseString(string s) {
        string str;
        if(s != "\0"){
            str = reverseString(s.substr(1, s.length()));
            str += s.substr(0,1);
        }
        return str;    
    }   
};

我知道我不应该给出解决方案,但既然没有人提到这个简单的解决方案,我想我应该分享它。 我认为代码字面上就是算法,所以不需要伪代码。

void c_plusplus_recursive_swap_reverse(std::string::iterator start, 
    std::string::iterator end) 
{
    if(start >= end) {
        return;
    }

    std::iter_swap(start, end);
    c_plusplus_recursive_swap_reverse(++start, --end);
}

调用它使用:

c_plusplus_recursive_swap_reverse(temp.begin(), temp.end());

1 行递归解决方案:

string RecursiveReverse(string str, string prev = "") {
    return (str.length() == 0 ? prev : RecursiveReverse(str.substr(0, str.length()-1), prev += str[str.length()-1]));
}

你这样称呼它:

cout << RecursiveReverse("String to Reverse");

所有现有的解决方案都有太多的代码没有真正做任何事情,所以,这是我的看法:

#include <iostream>
#include <string>

std::string
r(std::string s)
{
    if (s.empty())
        return s;
    return r(s.substr(1)) + s[0];
}

int
main()
{
    std::cout << r("testing") << std::endl;
}

PS 我偶然发现了这个问题,试图为 C 中的char * s+1 std::string找到一种 C++ 方式; 没有走s.substr(1, s.length()-1)的整个路线,这看起来太难看了。 原来,有std::string::npos ,这意味着直到字符串的末尾,它已经是第二个参数的默认值,所以, s.substr(1)就足够了(另外,它看起来也更有效率并与 C 中的简单s + 1相当)。


但是请注意,递归通常不会随着输入变大而扩展,除非编译器能够执行所谓的尾递归优化。 (命令式语言很少依赖递归。)

但是,为了使尾递归优化被激活,一般要求,(0),递归只发生在return语句中,并且,(1),递归的结果不执行进一步的操作在父函数中回调。

例如,在上述情况下, + s[0]在子调用完成后由父级逻辑完成(即使您使用更丑陋的s[s.length()-1] +路由也可能如此),因此,它也可能阻止大多数编译器进行尾递归优化,从而使该函数在大输入上非常低效(如果不是由于堆耗尽而完全损坏)。

(对于它的价值,我已经尝试编写一个对尾递归更友好的解决方案(确保通过函数本身的参数来增加返回结果),但是对生成的二进制文件的反汇编似乎表明它比在像 C++ 这样的命令式语言中,请参阅gcc:如果我在 C++ 中返回 std::string,是否没有尾递归? 。)

您可以实现类似于 std::reverse 的自己的反向。

template <typename BidirIt>
void reverse(BidirIt first, BidirIt last)
{
    if((first == last) || (first == --last))
        return;

    std::iter_swap(first, last);
    reverse(++first, last);
}

我做了这样的事情,它在原地进行了逆转。 我取了两个变量,它们从字符串的两端到字符串的中心遍历字符串,当它们相互重叠或相等时,反转终止。

举个例子:输入string str = "abcd"并调用函数为

ReverseString(str,0,str.length()-1);

并递归地递增/递减变量指针。 首先指针指向'a''d'并交换它们,然后它们指向'b''c'并交换它们。 最终i >= j要求基本情况为真,因此递归终止。 这个问题的主要内容是将输入字符串作为参考传递。

string ReverseString(string& str,int i,int j){
        if(str.length() < 1 || str == "" || i >= j){
            return "";
        }

        else{
            char temp = str[i];
            str[i] = str[j];
            str[j] = temp;
            ReverseString(str,i+1,j-1);
        }
        return str;
    }

字符串可以就地反转。 如果我们从尽可能小的字符串开始,即一个字符串,我们不需要做任何事情。 这是我们停止或从递归调用返回的地方,它成为我们的基本情况。

接下来,我们必须考虑交换最小字符串的通用方法,即两个或更多字符。 最简单的逻辑是将当前字符str[current_index]与对面的字符str[str_length-1 - current_index]

最后,再次为下一个索引调用反向函数。

#include <iostream>
using namespace std;

void reverse_string(std::string& str, int index, int length) {
  // Base case: if its a single element, no need to swap
  // stop swapping as soon as we reach the mid, hence index*2
  // otherwise we will reverse the already reversed string
  if( (length - index*2) <= 1 ) { 
    return;
  }

  // Reverse logic and recursion:

  // swap current and opposite index
  std::swap(str[index], str[length-1 - index]); 

  // do the same for next character (index+1)
  reverse_string(str, index+1, length);
}

int main() {
  std::string s = "World";
  reverse_string(s, 0, s.length());
  std::cout << s << endl;
}

已经有一些很好的答案,但我想用完整的递归反向字符串添加我的方法。

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

char * reverse_s(char *, char*, int,int);

int main(int argc, char** argv) {
if(argc != 2) {
        cout << "\n ERROR! Input String";
        cout << "\n\t " << argv[0] << "STRING" << endl;
        return 1;
}       
        char* str = new char[strlen(argv[1])+1];
        strcpy(str,argv[1]);    
        char* rev_str = new char[strlen(str)+1];        
        cout<<"\n\nFinal Reverse of '" << str << "' is --> "<< reverse_s(str, rev_str, 0, strlen(str)) << endl;
        cin.ignore();
        delete rev_str, str;
        return 0;
}

char* reverse_s(char* str, char* rev_str, int str_index, int rev_index ) {
if(strlen(str) == 1)
        return str;

if(str[str_index] == '\0' ) {
        rev_str[str_index] = '\0';
        return rev_str;
}

str_index += 1;
rev_index -=1;

rev_str = reverse_s(str, rev_str, str_index, rev_index);
if(rev_index >= 0) {
        cout << "\n Now the str value is " << str[str_index-1] << " -- Index " << str_in
dex << " Rev Index: " << rev_index;
        rev_str[rev_index] = str[str_index-1];

        cout << "\nReversed Value: " << rev_str << endl;
}
return rev_str;
}
void reverse(string &s, int &m) {
    if (m == s.size()-1)
        return;
    int going_to = s.size() - 1 - m;
    string leader = s.substr(1,going_to);
    string rest = s.substr(going_to+1,s.size());
    s = leader + s.substr(0,1) + rest;
    reverse(s,++m);    
}
int main ()
{
  string y = "oprah";
  int sz = 0;
  reverse(y,sz);
  cout << y << endl;
  return 0;
}

这是我的 3 行字符串反转

std::string stringRevers(std::string s)
{
    if(s.length()<=1)return s;
    string word=s.at(s.length()-1)+stringRevers(s.substr(0,s.length()-1));//copy the last one at the beginning  and do the same with the rest
    return word;

}
void ClassName::strgRevese(char *str)
{
        if (*str=='\0')
                return;
        else
                strgRevese(str+1);
        cout <<*str;
}

问题是写一个递归函数。 这是一种方法。 不是一个整洁的代码,但做了什么需要。

/* string reversal through recursion */
#include <stdio.h>
#include <string.h>
#define size 1000
char rev(char []);
char new_line[size];
int j = 0;
int i =0;
int main ()
{
  char string[]="Game On";
  rev(string);
  printf("Reversed rev string is %s\n",new_line);
  return 0;
}
char rev(char line[])
{
 while(line[i]!='\0')
  { 
    i++;
    rev(line);
    i--;
    new_line[j] = line[i];
    j++;
    return line[i];
  }
  return line[i];
}

它将递归地反转原始字符串

void swap(string &str1, string &str2)
{
    string temp = str1;
    str1 = str2;
    str2 = str1;
}

void ReverseOriginalString(string &str, int p, int sizeOfStr)
{
    static int i = 0;
    if (p == sizeOfStr)
        return;

    ReverseOriginalString(str, s + 1, sizeOfStr);

    if (i <= p)
        swap(&str[i++], &str[p])
}

int main()
{
    string st = "Rizwan Haider";

    ReverseOriginalString(st, 0, st.length());
    std::cout << "Original String is Reversed: " << st << std::endl;

    return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM