简体   繁体   中英

Recursive Substring Reversal in C++

I do not understand why the following code does not work for this. The task of this program was to reverse a section of a string based on two indices recursively. I have tried many alternate methods using swap() and different start and end conditions for the base case of the recursion. I feel really dumb right now and I am waiting for someone to point out the obvious to me.

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

string recurseReverse(string str, int start, int end);

int main() {
cout << "Starting string: ";
string alphabet = "abcdefghijklmnopqrstuvwxyz";
cout << alphabet;

cout << "Passing reverse the string along with values 11 and 18 for indices." << endl;
alphabet = recurseReverse(alphabet, 11, 18);
cout << alphabet << endl;

cout << "Passing reverse the string along with values 5 and 23 for indices." << endl;
alphabet = recurseReverse(alphabet, 5, 23);
cout << alphabet << endl;

cout << "Realphebetizing the string." << endl;
sort(alphabet.begin(), alphabet.end());
cout << alphabet << endl;

cout << "Dealphebetizing the string." << endl;
alphabet = recurseReverse(alphabet, 0, 25);
cout << alphabet << endl;

return 0;
}

string recurseReverse(string str, int start, int end) {
char temp = ' ';

if(start < end) {
temp = str[end - 1];
str[end - 1] = str[end];
str[end] = temp;
str = recurseReverse(str, start, end - 1);
}

return str;
}

I assume that you want to fully reverse the string, eg:

recurseReverse("abcde", 0, 4) => "edcba"

The problem is that you are swapping consecutive elements. So on the first call, you swap round d and e, and then the d forever remains at the end of the string.

Instead, you should be swapping the first and last elements of the string, and then moving in from both sides.

string recurseReverse(string str, int start, int end) {

  if(start < end) {
    std::swap(str.at(start), str.at(end));
    str = recurseReverse(str, start + 1, end - 1);
  }

  return str;
}

You should use .at() here, because it will throw if start or end are outside the length of the string (eg you passed in -1, or 26).

I assume that recursion was specified as part of the assignment, but it seems like a poor choice here. If your substring was, say, a million characters long, the program would need to keep track of a million function calls - which would more than likely result in a stack overflow . In my opinion, the humble for loop seems better suited to this task.

std::string reverseSubstring(std::string str, size_t start, size_t end) {

for(size_t left = start, right = end; left < right; ++left, --right)
{
    std::swap(str.at(left), str.at(right));
}

return str;
}

and if I was writing production code, rather than an assignment, I would just get the STL to do it for me:

std::string reverseSubstring(std::string str, size_t start, size_t end) {

  if(start >= end || start < 0 || end >= str.size())
  {
    throw std::invalid_argument("start and end must be valid, and start must be before end");
  }
  std::reverse(str.begin() + start, str.begin() + end + 1);

  return str;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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