9

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.

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)

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. 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

Alex
  • 3,111
  • 6
  • 27
  • 43

18 Answers18

19

I'll instead explain the recursive algorithm itself. Take the example "input" which should produce "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.
templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
David Harkness
  • 35,992
  • 10
  • 112
  • 134
  • Your post is the most helpful so far – Alex Apr 22 '11 at 22:58
  • I tried implementing this using C++ and the speed is very slow compared to using an iterator – ArmenB Jul 16 '15 at 21:45
  • @ArmenB. Algorithm selection often requires choosing among runtime speed, memory requirements, and complexity. – David Harkness Jul 17 '15 at 23:46
  • @DavidHarkness: I agree. But in this case, I don't see any benefit of this method over using an iterator. Memory wise it's uses more, runtime speed is slower, code complexity is a bit complex too. – ArmenB Jul 20 '15 at 18:05
  • 1
    @ArmenB. Keep in mind that the question *asked* for a recursive implementation. – David Harkness Jul 21 '15 at 07:09
  • 1
    That approach uses O(n) stack space. You could reduce this to O(log n), by splitting the string in half, reverse the last half, reverse the first half, add the two reversed halves together, and return the new string. Perhaps not as clear and straight forward as your solution, but not by that much. – AJNeufeld Mar 30 '16 at 17:33
7

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. If it would be the other way around nothing would happen.

It is very inefficient but it works to show the concept.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
Alois Kraus
  • 13,229
  • 1
  • 38
  • 64
  • @braaterAfrikaaner: I have no idea what you are referring to. Might the clue be in the date of your comment?? – sbi Apr 06 '18 at 12:08
6

Just to suggest a better way of handling recursion:

String reversal using recursion in 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;
}
totjammykd
  • 337
  • 4
  • 10
2

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
}
Ann Orlova
  • 1,338
  • 15
  • 24
2

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.

Community
  • 1
  • 1
sbi
  • 219,715
  • 46
  • 258
  • 445
  • Yes the book said to write the function `string reverse(string str)`. – Alex Apr 22 '11 at 22:56
  • Also, algorithms are easy. I have mine except recursion is a confusing concept for me and I don't know how to write the function using recursion – Alex Apr 22 '11 at 22:57
  • @Alex: Don't feel bad, recursion is a difficult concept to grasp. Have you looked at other examples, such as the recursive Fibonacci algorithm? Try to work out the 5th Fibonacci number recursively, by hand (**on paper**) before attempting to write any code. – Emile Cormier Apr 22 '11 at 23:01
  • I thought so. I might try that – Alex Apr 22 '11 at 23:04
  • 2
    @sbi: The book is most likely trying to explain recursive functions in the simplest terms possible, without any regard to efficiency. That signature makes sense from a pedagogical standpoint. – Emile Cormier Apr 22 '11 at 23:07
  • Yes. Preface page 10 was titled "The Pedagogical Structure" – Alex Apr 22 '11 at 23:11
  • @Alex: Recursively working out the factorial of, say, 4, might be a better first exercise than Fibonacci. – Emile Cormier Apr 22 '11 at 23:21
  • @Emile: Having taught C++ for more than a decade, I beg to differ. I have learned (the hard way), that students won#t be able to differentiate between relevant code you wrote properly and the improperly written "irrelevant" code. If you're lucky, they'll remember both with the same intensity. As teacher you always need to do it right, and ___teaching C++ so that your students can learn one thing at a time without ever being exposed to code they should forget about is exactly what makes teaching C++ so hard___. – sbi Apr 22 '11 at 23:23
  • @sbi: Can't argue with someone who actually taught this stuff. :-) You make a good point... as illustrated by the many times I've seen `using std;` being used indiscriminately because beginners are accustomed to seeing it used in textbooks. – Emile Cormier Apr 22 '11 at 23:31
  • @Emile: Exactly. I'm all up in rage about books omitting the `std`. No matter how intensely the authors tell their audience that it is just done for the sake of formatting in the book (if they even do that), everyone reading those books will adopt the idiom and then [run into inexplicable trouble](http://stackoverflow.com/questions/2879555/c-stl-how-to-write-wrappers-for-cout-cerr-cin-and-endl/2880136#2880136). – sbi Apr 23 '11 at 22:55
  • @sbi just revisiting my earliest questions for kicks after ~5 years of programming. Honestly, I don't think passing by value was important at all at this point. I didn't have any notions of of algorithmic efficiency, and knew absolutely nothing about objects, lifetimes, scopes, copy, move, assignment etc. I was too busy trying to figure out the "right ways" to do things, and the valid syntax to string/hack structures together into a seemingly correct program – Alex Mar 11 '16 at 04:22
  • Sure, this book may not be great, but it kept things simple with some good exercises, and taught me enough fundamentals to form a solid stepping stone. I went with Java mostly after, but came back last year with C++ Primer, one of the recommended ones. I learned so much more, but it's still a reference nontheless. They often put more effort into details, and beginners often lose interest because normal people are not used to thinking with such granularity – Alex Mar 11 '16 at 04:23
  • IMHO, I don't think there's a single right way to teach something. Some learn top down, and others bottom up. I don't think it's good to overload beginners with efficiency topics and other little details until later on. It's much easier to remember why certain things are done a certain way, or those little rules if you know the reason behind it, and that comes with experience most of the time – Alex Mar 11 '16 at 04:23
  • @Alex: That's your opinion. Fair enough. But I disagree. Experience has shown me that it is much harder to unlearn a bad habit you got into when you started to learn something than to do it the right way right from the start. Yes, this raises the bar in the beginning, but IMO that's worth it. Three more points: 1. Having just come back from Java you might not yet fully appreciate the importance of how to pass arguments in C++. 2. There's move semantics now, which alleviate the negative effects a bit. 3. I learned C++ in the early 90s and still need to look things up regularly. C++ is a beast. – sbi Mar 13 '16 at 20:05
  • @sbi I am aware of all the semantics. You try to use automatic memory management as much as possible, and avoid using raw pointers. That's one difference between Java and C++. I even try to keep const correctness when I'm not doing a scratch project lol. By coming back, I meant "trying to use C++ full time". I did use it on and off, read the Primer (latest version for C++11), and follow its development every now and then before fully switching. Sorry for being unclear – Alex Mar 13 '16 at 21:20
  • I guess it could be that most other students tend to memorize for tests, then carry on with their lives, not bothered to figure out what actually goes on beneath the hood, and why all these semantics are needed until many years into their job. In this case, yeah it'll probably enable them to develop bad habits that they won't correct for fear of breaking something after finally getting it right. PS C++ absolutely is a beast. I'm amazed how well GCC and Clang works – Alex Mar 13 '16 at 21:20
  • @Alex: The type of students that tend to memorize things tended to get sorted out of my courses rather quickly. I have also taught C++ to absolute beginners which were learning to program. My experience is that those learning cannot tell between the important code you wrote correctly and the unimportant code you just sketched out because it was needed. They pick their habits from both. So I learned to absolutely always show correct code, no matter how unimportant the code seemed to me. – sbi Mar 13 '16 at 22:22
1

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

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());
ArmenB
  • 2,125
  • 3
  • 23
  • 47
0

1-line recursive solution:

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");
PieThon
  • 11
  • 1
  • 3
0

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

P.S. I stumbled upon this question trying to find a C++ way for std::string of what s+1 for a char * in C is; without going the whole route of s.substr(1, s.length()-1), which looks too ugly. 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).


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.

E.g., 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).

(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++?.)

Community
  • 1
  • 1
cnst
  • 25,870
  • 6
  • 90
  • 122
0

you can implement your own reverse similar to 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);
}
MORTAL
  • 383
  • 2
  • 10
0

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

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. Eventually i >= j which calls for the base case to be true and hence the recursion terminates. 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;
    }
Marco167
  • 371
  • 3
  • 7
0

String can be reversed in-place. If we start from smallest possible string i.e. 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 i.e. 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].

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;
}
SMUsamaShah
  • 7,677
  • 22
  • 88
  • 131
-1

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;
}
Ankit Singh
  • 2,602
  • 6
  • 32
  • 44
-1
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;
}
-1

here is my 3 line string revers

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;

}
SRedouane
  • 498
  • 5
  • 10
-1
void ClassName::strgRevese(char *str)
{
        if (*str=='\0')
                return;
        else
                strgRevese(str+1);
        cout <<*str;
}
srhaider
  • 17
  • 4
-2

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];
}
SandBag_1996
  • 1,570
  • 3
  • 20
  • 50
-2

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;
}
Alex
  • 3,111
  • 6
  • 27
  • 43
srhaider
  • 17
  • 4
  • In your `swap()`, you can't assign `char` to a `string` – Alex Jun 22 '19 at 19:10
  • Working Perfectly to reverse any string, char was mistaken – srhaider Jun 23 '19 at 21:54
  • Are you sure? `s` should be `p` in `ReverseOriginalString`. Your swap takes references, but you're passing in pointers when you called it in `ReverseOriginalString`. `std::swap()` already exists anyway. It also uses a static variable that's never ever reset, so your function can only be called no more than once throughout the entire runtime of your program – Alex Jun 23 '19 at 22:27