簡體   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