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

时间:2011-04-22 22:47:16

标签: c++ recursion reverse

我一直在读“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

18 个答案:

答案 0 :(得分:19)

我有两分钟,所以我会解释递归算法本身。以“输入”为例,它应该产生“tupni”。您可以通过

递归反转字符串
  • 如果字符串为空或单个字符,请将其保持不变。
  • 否则,
    1. 删除第一个字符。
    2. 翻转剩下的字符串。
    3. 将上面的第一个字符添加到反向字符串中。
    4. 返回新字符串。

答案 1 :(得分:7)

试试这个

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
}

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

  • 必须再次召唤自己
  • 递归结束时必须有条件否则你有一个函数 将导致stackoverflow。

这个递归函数基本上创建了一个最后一个字符的字符串,然后再次使用除最后一个字符之外的其余字符串调用自身。实际切换发生在返回last + reversed的最后一行。如果反过来会发生任何事情。 这是非常低效的,但它可以显示这个概念。

此致,    Alois Kraus

答案 2 :(得分:6)

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

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

答案 3 :(得分:2)

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

如何交换两个最外面的字符,然后将它们应用到中间的字符?

哦,如果那本书真的提出string reverse(string str)作为适当的功能签名,请将其丢弃并改为购买good book

答案 4 :(得分:2)

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

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
}

答案 5 :(得分:1)

最短,最简单

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

答案 6 :(得分:0)

字符串可以就地反转。如果我们从最小的字符串(即一个字符串)开始,则无需执行任何操作。这是我们停止或从递归调用返回的地方,它成为我们的基本情况。

接下来,我们必须考虑一种交换最小字符串(即两个或更多字符)的通用方法。最简单的逻辑是将当前字符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;
}

答案 7 :(得分:0)

我做了类似的事情,它做了逆转。我从字符串的两个极端到字符串的中心处取两个变量遍历字符串,当它们重叠或相等时,则反转终止。

举个例子:输入'a'并将函数调用为

'd'

以递归方式递增/递减变量指针。 首先,指针指向'b''c'并交换它们,然后它们指向i >= jstring 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; } 并交换它们。最终var friends = [{ friend_id: 3, friend_name: 'Jim' }, { friend_id: 14, friend_name: 'Selma' }]; _.remove(friends, friend => friend.friend_id === 14); console.log(friends);调用基本情况为真,因此递归终止。这个问题的主要内容是传递输入字符串作为参考。

<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.js"></script>

答案 8 :(得分:0)

你可以实现自己的反向,类似于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);
}

答案 9 :(得分:0)

所有现有的解决方案都有太多的代码,并没有真正做任何事情,因此,我的理解是:

#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。我偶然发现了这个问题,试图为std::string找到C s+1char *的C {s.substr(1, s.length()-1)。没有走std::string::npos的整个路线,看起来太难看了。事实证明,有s.substr(1),这意味着直到字符串结束,并且它已经是第二个参数的默认值,因此,s + 1就足够了(加上,它也看起来效率更高,与C中的简单return相同。

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

但是,为了使尾递归优化被激活,通常要求(0)递归仅在+ s[0]语句中发生,并且,(1),没有进一步的操作是使用父函数中的递归回调结果执行。

例如,在上面的情况中,s[s.length()-1] +在子调用完成后由父项逻辑完成(即使你去了更加丑陋的clang++ -O3路由,它也可能是这样),所以,它也可以防止大多数编译器进行尾递归优化,从而使得函数在大输入上效率非常低(如果由于堆耗尽而没有完全破坏)。

(对于它的价值,我已经尝试编写了一个更符合尾递归的解决方案(确保通过函数本身的参数增加返回结果),但是反汇编结果二进制似乎表明它比C ++这样的命令式语言更复杂,请参阅gcc: is there no tail recursion if I return std::string in C++?。)

答案 10 :(得分:0)

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

答案 11 :(得分:0)

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

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

答案 12 :(得分:-1)

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

答案 13 :(得分:-1)

这是我的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;

}

答案 14 :(得分:-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;
}

答案 15 :(得分:-1)

已经有一些很好的答案,但我想用完整的Recursive reverseing 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;
}

答案 16 :(得分:-2)

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

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

答案 17 :(得分:-2)

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

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