我正在尝试编写一个反转字符串的递归函数,我很确定我的递归基础是可靠的,但我无法让它工作......
基础:如果长度<= 1,则停止。 否则,交换第一个和最后一个元素并向前推进一个元素并将长度减少1.
我在缩短长度方面遇到了麻烦......
我考虑过使用strcat
并在每次递归时添加前面的第一个元素,但它只对常量有用...
注2:我无法更改该功能的签名,我也无法使用任何其他库。
不要编辑我在这里使用的库和命令。这些是我所知道和使用的。
#include <string.h>
#include <iostream>
using namespace std;
void recuverse(char s[]);
int main()
{
char s[] = "abcde";
recuverse(s);
cout << s << endl;
}
void recuverse(char s[]){
int len = strlen(s);
int i;
if (len <= 1)return;
else{
for (i = len-1; i>0; i--){
swap(s[0], s[i]);
recuverse(s + 1);
}
}
}
答案 0 :(得分:2)
实现中的for
循环不是必需的:由于具有该循环,您执行的交换太多。事实上,这个练习的重点一直是消除循环。
通过添加一个测量字符串长度的额外函数来修复您的实现,然后调用两个参数recuverse_impl
,如下所示:
void recuverse_impl(char *s, size_t len) {
// Base case
if (len < 2) return;
// Swap elements the two ends
swap(s[0], s[len-1]);
// then call recuverse_impl again
recuverse_impl(s+1, len-2);
}
void recuverse(char s[]){
recuverse_impl(s, strlen(s));
}
如果由于某种原因要求明确禁止传递长度,您可以按如下方式更改实现:
void recuverse(char *s) {
// Compute the length
size_t len = strlen(s);
// Do the base case
if (len < 2) return;
// Squirrel away the last element, and replace it with '\0'
char t = s[len-1];
s[len-1] = '\0';
// Make a recursive call
recuverse(s+1);
// Now complete the swap
s[len-1] = s[0];
s[0] = t;
}
答案 1 :(得分:2)
试试这个:
void recuverse(char s[])
{
int len = strlen(s);
if (len <= 1)
return;
char c = s[len-1];
s[len-1] = 0;
recuverse(s+1);
s[len-1] = s[0];
s[0] = c;
}
答案 2 :(得分:2)
尽我所知,这是通过这种不合理的限制来实现你所要求的唯一方法。
这是编写此函数的一种愚蠢的,愚蠢的方式,但我相信它符合指定指南中要求的内容。
// Reverses a string in place.
// Note: string cannot be a constant, without write permission
void reverse(char s[])
{
// Get string length
int len = strlen(s);
if (len > 2)
{
// Save last character
char lastChar = s[len - 1];
// Temporarily shorten string by replacing last character
// with a null-terminator character
s[len - 1] = '\0';
// Recursively swap remaining characters
reverse(s + 1);
// Swap first and last character
s[len - 1] = s[0];
s[0] = lastChar;
}
}
我认为上面的方法很糟糕,因为递归不是解决这个问题的最有效方法。即使使用递归,为此代码的递归部分编写单独的函数也会更有效,其中可能包含跟踪状态的其他参数,并在此处阻止某些重复逻辑。此外,避免使用任何其他库是没有意义的,特别是如果它包含将成为任何C ++应用程序一部分的库。
如果没有这些限制,我可以在这里编写反向函数。
void reverse(char* s)
{
char *pEnd = s + (strlen(s) - 1);
while (s < pEnd)
{
char c = *s;
*s++ = *pEnd;
*pEnd-- = c;
}
}
答案 3 :(得分:2)
我的C解决方案不使用额外的库(stdio而不是iostream)和相同的函数签名。
#include <stdio.h>
#include <string.h>
void recuverse(char s[]){
char saved;
int len = strlen(s);
if (len > 1) {
saved = s[len-1]; // keep last char
s[len-1] = 0; // shorten string
recuverse(s+1); // with shorter string
s[len-1] = s[0]; // replace last char with first
s[0] = saved; // replace first char with last
} // job done
}
int main()
{
char str0 [] = ""; // test with various
char str1 [] = "a";
char str2 [] = "ab";
char str3 [] = "abc";
char str4 [] = "abcd";
recuverse (str0);
printf ("'%s'\n", str0);
recuverse (str1);
printf ("'%s'\n", str1);
recuverse (str2);
printf ("'%s'\n", str2);
recuverse (str3);
printf ("'%s'\n", str3);
recuverse (str4);
printf ("'%s'\n", str4);
}
节目输出
''
'a'
'ba'
'cba'
'dcba'
答案 4 :(得分:2)
似乎我已经理解了你需要的是你想要实现的方法。
您可以编写类似
的功能void recuverse( char s[] )
{
recuverse( s , std::strlen( s ) );
}
void recuverse( char s[], size_t n )
{
if ( !( n < 2 ) )
{
std::swap( s[0], s[n-1] );
recuverse( s + 1, n - 2 );
}
}
但它是一个错误的解决方案,因为它不是函数void recuverse( char s[] );
,它是一个递归函数。函数void recuverse( char s[], size_t n );
是递归的。但根据你的任务,函数void recuverse( char s[] );
应该是递归的。
所以唯一正确的解决方案如下。
#include <iostream>
#include <utility>
char * recuverse( char s[] )
{
if ( *s )
{
char *p = s;
do
{
std::swap( *p, *( p + 1) );
} while ( *p++ );
recuverse( s );
std::swap( *p, *( p - 1 ) );
}
return s;
}
int main()
{
char s[] = "abcde";
std::cout << s << std::endl;
std::cout << recuverse( s ) << std::endl;
return 0;
}
输出
abcde
edcba
这个递归函数既不使用除std::swap
之外的标准函数,也可以替换代码。:)
我更喜欢该函数的返回类型char *
与标准C字符串函数类似。如果您希望该函数具有返回类型void
,那么它将看起来像
void recuverse( char s[] )
{
if ( *s )
{
char *p = s;
do
{
std::swap( *p, *( p + 1) );
} while ( *p++ );
recuverse( s );
std::swap( *p, *( p - 1 ) );
}
}
为了理解这个反向函数如何在没有标准函数strlen
的情况下工作,让我们使用简化的例子“abc”逐步考虑它的操作。
所以我们有一个终止为零的字符串
abc\0
我将写为abc0
while循环
while ( *p++ ) ...
交换字符,直到它将交换终止零。
在第一次递归调用中,循环正在执行以下操作
abc0
bac0
bca0
bc0a
现在函数调用自身,但现在字符串看起来像
BC0
所以在循环中会有
bc0
cb0
c0b
在下一个递归调用中,参数将为
C0
在循环中交换两个字符
0c
所以最后用空字符串调用该函数。因此它只是将控件返回给调用者,调用者交换字符串的最后一个字符
考虑到整个字符串现在看起来像
0cba
我们需要将终止零tp移动到字符串末尾的有效位置。这是通过循环后的交换来完成的。
0c => c0
--------
c0b => cb0
-----------
cb0a => cba0
就是这样。:)
答案 5 :(得分:1)
这里是递归反向的正确版本:
void reverse(char *s, char *e) {
if (s < e) {
char t = *s;
*s = *e;
*e = t;
reverse(s+1, e-1); // here is length is decreased by 2
}
}
void recuverse(char s[]) {
int len = strlen(s);
reverse(s, s+len-1);
}
答案 6 :(得分:1)
这不是改变签名,而是使用std::swap
交换s [begin]和s [end]直到它到达中间。要完成递归并保留签名,你可以(doens并不意味着你应该)将begin,mid和length声明为全局变量:
int beg = 0;
int len = 0;
int mid = 0;
void recuverse(char s[]) {
if (beg == 0) { // this block runs one time.
len = strlen(s)-1;
mid = len / 2;
}
if (beg == mid)
return;
swap(s[beg], s[len]);
++beg, --len;
recuverse(s);
}
输出:edcba
答案 7 :(得分:1)
如果允许使用静态变量,请尝试使用
void recuverse(char s[]){
static int e;
int z=strlen(s)-e++; // z is the number of characters to be evaluated
if(z>1){
char t=*(s+z-1);
*(s+z-1)=*s;
*s=t;
recuverse(s+1);
}
}
答案 8 :(得分:0)
如果您注意mirror(cs) = cat(mirror(s),c)
(c
是字符,s
是字符串),那么:
void rev(char *s) {
if (*s==0) return;
rev(s+1);
sprintf(s,"%s%c",s+1,*s);
}
答案 9 :(得分:0)
在C ++实现下,递归反转字符串
这里基础案例是在字符串
中找到NULL字符 #include<bits/stdc++.h>
using namespace std;
void reverse(string s,long i){
if(s[i] == '\0')
return;
reverse(s,i+1);
cout<<s[i];
return;
}
int main(){
string s;
cin>>s;
reverse(s,0);
return 0;
}
答案 10 :(得分:-1)
你可以试试这个:
#include <string.h>
#include <iostream>
using namespace std;
void recuverse(char *s, int right);
int main()
{
char s[] = "abcde";
recuverse(s , 0);
cout << s << endl;
}
void recuverse(char *s, int right){ // Here right is the position of the right position(from right to left) of character with which you will swap
int len = strlen(s);
int i;
if (len <=right)return;
swap(s[0], s[len-1-right]);
recuverse(s + 1, right+1);
}