简体   繁体   English

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

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

I've been reading the book C++ For Everyone and one of the exercises said to write a function string reverse(string str) where the return value is the reverse of str .我一直在阅读 C++ For Everyone 一书,其中一个练习说要编写一个函数string reverse(string str) ,其中返回值是str的反向。

Can somebody write some basic code and explain it to me?有人可以写一些基本的代码并向我解释吗? I've been staring at this question since yesterday and can't figure it out.我从昨天开始就一直盯着这个问题,想不通。 The furthest I've gotten is having the function return the first letter of str (Which I still don't know how it happened)我得到的最远的是让函数返回str的第一个字母(我仍然不知道它是怎么发生的)

This is as far as I got (An hour after posting this question):这是我得到的(发布这个问题一个小时后):

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;
}

If I enter "Wolf", it returns Wol.如果我输入“Wolf”,它会返回 Wol。 Somebody help me out here If I return word instead of return str_copy then I get a w If I return last_letter then I get an l有人帮我在这里如果我return word而不是return str_copy那么我得到一个w如果我return last_letter那么我得到一个l

I'll instead explain the recursive algorithm itself.相反,我将解释递归算法本身。 Take the example "input" which should produce "tupni".以应该产生“tupni”的“输入”为例。 You can reverse the string recursively by您可以通过递归反转字符串

  • If the string is empty or a single character, return it unchanged.如果字符串为空或单个字符,则原样返回。
  • Otherwise,除此以外,
    1. Remove the first character.删除第一个字符。
    2. Reverse the remaining string.反转剩余的字符串。
    3. Add the first character above to the reversed string.将上面的第一个字符添加到反转字符串中。
    4. Return the new string.返回新字符串。

Try this one试试这个

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
}

A recursive function must have the following properties递归函数必须具有以下属性

  • It must call itself again它必须再次调用自己
  • It must have a condition when the recursion ends.当递归结束时,它必须有一个条件。 Otherwise you have a function which will cause a stack overflow.否则你有一个函数会导致堆栈溢出。

This recursive function does basically create a string of the last character and then call itself again with the rest of the string excluding the last character.这个递归函数基本上创建了一个包含最后一个字符的字符串,然后用字符串的其余部分(不包括最后一个字符)再次调用自己。 The real switching happens at the last line where last+reversed is returned.真正的切换发生在返回 last+reversed 的最后一行。 If it would be the other way around nothing would happen.如果情况相反,则什么都不会发生。

It is very inefficient but it works to show the concept.这是非常低效的,但它可以展示这个概念。

Just to suggest a better way of handling recursion:只是建议一种更好的处理递归的方法:

String reversal using recursion in C++:在 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;
}

Here is my version of a recursive function that reverses the input string:这是我的递归函数版本,用于反转输入字符串:

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
}

I won't write a full-blown algorithm for you, but here's a hint:我不会为你写一个完整的算法,但这里有一个提示:

How about swapping the two outermost characters, and then apply the same to the characters in the middle?如何交换最外面的两个字符,然后将相同的应用于中间的字符?

Oh, and if that book really proposed string reverse(string str) as an appropriate function signature for this, throw it away and buy a good book instead.哦,如果那本书真的提出了string reverse(string str)作为合适的函数签名,那就扔掉它,买一本好书吧

Shortest and easiest最短和最简单

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;    
    }   
};

I know I shouldn't give a solution, but since no one mentioned this easy solution I though I should share it.我知道我不应该给出解决方案,但既然没有人提到这个简单的解决方案,我想我应该分享它。 I think the code literally is the algorithm so there is no need for a pseudo-code.我认为代码字面上就是算法,所以不需要伪代码。

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);
}

To call it use:调用它使用:

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

1-line recursive solution: 1 行递归解决方案:

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

You call it like this:你这样称呼它:

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

All existing solutions had way too much code that didn't really do anything, so, here's my take at it:所有现有的解决方案都有太多的代码没有真正做任何事情,所以,这是我的看法:

#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 I stumbled upon this question trying to find a C++ way for std::string of what s+1 for a char * in C is; PS 我偶然发现了这个问题,试图为 C 中的char * s+1 std::string找到一种 C++ 方式; without going the whole route of s.substr(1, s.length()-1) , which looks too ugly.没有走s.substr(1, s.length()-1)的整个路线,这看起来太难看了。 Turns out, there's std::string::npos , which means until the end of the string, and it's already the default value for the second argument, so, s.substr(1) is enough (plus, it also looks more efficient and on par with the simple s + 1 in C).原来,有std::string::npos ,这意味着直到字符串的末尾,它已经是第二个参数的默认值,所以, s.substr(1)就足够了(另外,它看起来也更有效率并与 C 中的简单s + 1相当)。


Note, however, that recursion in general doesn't scale as the input grows larger, unless the compiler is able to do what is known as tail-recursion optimisation.但是请注意,递归通常不会随着输入变大而扩展,除非编译器能够执行所谓的尾递归优化。 (Recursion is rarely relied upon in imperative languages.) (命令式语言很少依赖递归。)

However, in order for the tail recursion optimisation to get activated, it is generally required that, (0), the recursion only happens within the return statement, and that, (1), no further operations are performed with the result of the recursive call back in the parent function.但是,为了使尾递归优化被激活,一般要求,(0),递归只发生在return语句中,并且,(1),递归的结果不执行进一步的操作在父函数中回调。

Eg, in the case above, the + s[0] is logically done by the parent after the child call completes (and it probably would be so even if you go the more uglier s[s.length()-1] + route), so, it might as well prevent most compilers from doing a tail-recursion-optimisation, thus making the function very inefficient on large inputs (if not outright broken due to heap exhaustion).例如,在上述情况下, + s[0]在子调用完成后由父级逻辑完成(即使您使用更丑陋的s[s.length()-1] +路由也可能如此),因此,它也可能阻止大多数编译器进行尾递归优化,从而使该函数在大输入上非常低效(如果不是由于堆耗尽而完全损坏)。

(For what it's worth, I've tried writing a more tail-recursion-friendly solution (making sure to grow the return result through an argument to the function itself), but disassembly of the resulting binary seems to suggest that it's more involved than that in the imperative languages like C++, see gcc: is there no tail recursion if I return std::string in C++? .) (对于它的价值,我已经尝试编写一个对尾递归更友好的解决方案(确保通过函数本身的参数来增加返回结果),但是对生成的二进制文件的反汇编似乎表明它比在像 C++ 这样的命令式语言中,请参阅gcc:如果我在 C++ 中返回 std::string,是否没有尾递归? 。)

you can implement your own reverse similar to std::reverse.您可以实现类似于 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);
}

I did something like this, it did the reversal in place.我做了这样的事情,它在原地进行了逆转。 I took two variables that traverse the string from two extreme end to the centre of the string and when they overlap or equal to each other then reversal terminates.我取了两个变量,它们从字符串的两端到字符串的中心遍历字符串,当它们相互重叠或相等时,反转终止。

Take an example: input string str = "abcd" and call the function as举个例子:输入string str = "abcd"并调用函数为

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

and increment/decrement the variable pointers recursively.并递归地递增/递减变量指针。 First the pointers points to 'a' and 'd' and swap them, then they point to 'b' and 'c' and swap them.首先指针指向'a''d'并交换它们,然后它们指向'b''c'并交换它们。 Eventually i >= j which calls for the base case to be true and hence the recursion terminates.最终i >= j要求基本情况为真,因此递归终止。 The main take away for this question is to pass input string as reference.这个问题的主要内容是将输入字符串作为参考传递。

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;
    }

String can be reversed in-place.字符串可以就地反转。 If we start from smallest possible string ie one character string, we don't need to do anything.如果我们从尽可能小的字符串开始,即一个字符串,我们不需要做任何事情。 This is where we stop or return from our recursive call and it becomes our base case.这是我们停止或从递归调用返回的地方,它成为我们的基本情况。

Next, we have to think of a generic way to swap the smallest string ie two characters or more.接下来,我们必须考虑交换最小字符串的通用方法,即两个或更多字符。 Simplest logic is to swap the current character str[current_index] with character on the opposite side str[str_length-1 - current_index] .最简单的逻辑是将当前字符str[current_index]与对面的字符str[str_length-1 - current_index]

In the end, call the reverse function again for next 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;
}

There are already some good answer but I want to add my approach with full working Recursive reversing string.已经有一些很好的答案,但我想用完整的递归反向字符串添加我的方法。

#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;
}

here is my 3 line string revers这是我的 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;
}

The question is to write a recursive function.问题是写一个递归函数。 Here is one approach.这是一种方法。 Not a neat code, but does what is required.不是一个整洁的代码,但做了什么需要。

/* 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];
}

It will reverse Original string recursively它将递归地反转原始字符串

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