C语言刷题:递归

1.分析下列递归函数。

解析:

2.逆序打印字符串。

具体题目:编写一个函数 reverse_string(char * string)(递归实现),将参数字符串中的字符反向排列,不是逆序打印。例如“abcdefg”,逆序后变为“gfedcba”。

解析:
对于字符串“abcdefg”,递归实现的大概原理:把a和g交换,然后把剩下的bcdef看成一个整体,再次进行相同的操作,即把b和f交换,依此类推;但是,当我交换完a和g之后,剩下的字符串abcdef就无法看成一个字符串了(没有'\0'结尾),所以我们将该步骤变为:

把a备份出来;

把g的值赋给a的位置;

把原来g的位置放上'\0';

逆序中间的bcdef;

最后再把a放到原来g的位置;

 依据这个思路,一开始,我们可能会写出这样的版本:
 

void reverse_string(char* arr)
{
	int len = strlen(arr);
	char tmp = *arr;
	*arr = *(arr + len - 1);

	*(arr + len - 1) = '\0';

    reverse_string(arr + 1);

	*(arr + len - 1) = tmp;
}
int main()
{
	char arr[] = "abcdef";
	reverse_string(arr);
	printf("%s\n", arr);
	return 0;
}

        但显然,这个代码是有问题的,一旦进入reverse_string函数就递归,则会形成死递归,没有跳出递归的条件。我们思考,当中间的字符串只剩下1个字符时,就没有必要进行交换了,而中间的字符串还剩2个及以上时,才有必要进行交换,所以我们添加一个判断条件,保证中间的字符串是大于等于2时,才进行递归。

        改正版本:

void reverse_string(char* arr)
{
	int len = strlen(arr);
	char tmp = *arr;
	*arr = *(arr + len - 1);

	*(arr + len - 1) = '\0';
	if (strlen(arr + 1) >= 2)
		reverse_string(arr + 1);

	*(arr + len - 1) = tmp;
}
int main()
{
	char arr[] = "abcdef";
	reverse_string(arr);
	printf("%s\n", arr);
	return 0;
}

3.计算一个数的每位之和

写一个递归函数DigitSum(n),输入一个非负整数,返回组成它的数字之和例如,调用DigitSum(1729),则应该返回1+7+2+9,它的和是19。输入:1729,输出:19

int DigiSum(size_t n)
{
	if (n <= 9)
		return n;
	else
		return DigiSum(n / 10) + n % 10;
}

int main()
{
	size_t num = 0;
	scanf("%u", &num);
	int ret = DigiSum(num);
	printf("%d\n", ret);
	return 0;
}

        注意:不要想着创建临时变量存储每位之和,非常不方便;不如直接返回函数的计算值。

 4.递归实现n的k次方。

double Pow(int n, int k)
{
	if (k == 0)
		return 1;
	else if (k > 0)
		return n * Pow(n, k - 1);
	else
		return 1.0 / Pow(n, -k);
}
int main()
{
	int n = 0;
	int k = 0;
	scanf("%d %d", &n, &k);

	double ret = Pow(n, k);

	printf("%lf\n", ret);
	return 0;
}

 这个比较简单,将其分为三种情况,进行讨论即可。

4.经典的斐波那契额数列问题

什么是斐波那契额数列?

        斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardo Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34……在数学上,斐波那契数列以如下被以递推的方法定义:F(0)=0,F(1)=1, F(n)=F(n - 1)+F(n - 2)(≥ 2,∈ N*)。

4.1走台阶问题

        亚东上课需要走n阶台阶,因为他腿比较长,所以每次可以选择走一阶或者走两阶,那么他一共有多少种走法?

分析:

假设走10级台阶,那么最后一步只有两种情况,要么走1阶,要么走2阶。如果最后一步走1阶,那么前9级台阶又有f(9)种走法;如果最后一步走2阶,那么前8级台阶又有f(8)种走法。而对于前9级(或前8级)台阶的走法,最后一步任然是两种情况,又可以依次类推,这就是典型的斐波那契数列。实现代码如下:

#include<stdio.h>
int choose(int num)
{
    if(num==1)
        return 1;
    else if(num==2)
        return 2;
    else
        return choose(num-1)+choose(num-2);
}
int main()
{
    int n=0;
    scanf("%d",&n);
    int a=choose(n);
    printf("%d",a);
return 0;
}

运行结果如下:

注意:走台阶问题用到的斐波那契数列形式为:1、2、3、5、8、13、21、34…,因为当有2级台阶时,已经有2种走法了。

 4.2兔子繁衍问题

        一对兔子,从出生后第3个月起每个月都生一对兔子。小兔子长到第3个月后每个月又生一对兔子。输入一个数,求出该月总共的兔子数。(第1个月有一对刚出生的兔子)

#include<stdio.h>
int choose(int num)
{
    if (num == 1)
        return 1;
    else if (num == 2)
        return 1;
    else
        return choose(num - 1) + choose(num - 2);
}
int main()
{
    int n = 0;
    scanf("%d", &n);
    int a = choose(n);
    printf("%d", a);
    return 0;
}

注意:这里的兔子繁衍问题用到的斐波那契数列形式为:1、1、2、3、5、8、13、21、34…因为当第2个月时,任然只有1对兔子。

4.3汉诺塔问题

汉诺塔

经典汉诺塔问题是,将A中的圆圈,全部移动到C上,每次只能移动一个圆圈,并且要保证大圈在下,小圈在上。 (B作为桥梁)

分析:

        当只有2个圈时,只需将‘1’放到B上,然后将‘2’放到C上,最后将‘1’放到C上即可;

        当有3个圈时,则将上面两个看成一个整体,然后将‘1’放到B上,将‘2’放到C上,最后将‘1’放到C上即可;当然,这时候将‘1’放到C上,就要借助于A了。

        在解决汉诺塔问题时,一定要明确三个塔的关系,一个是圈的其实位置,一个是圈的最终位置,剩下一个则是辅助位置。

解题步骤及伪代码

 

标题

 代码实现

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

void move(int n, char x, char y) 
{
    printf("第%d个盘子从%c--->%c\n", n, x, y);
}

void hanoi(int n, char A, char B, char C) 
{
    if (n == 1)
    {
        move(n, A, C);//如果只有一个模块,直接从  A 移动到  C
    }
    else 
    {
        hanoi(n - 1, A, C, B);//将 n-1个模块从  A 移动到  B
        move(n, A, C);
        hanoi(n - 1, B, A, C); //将 n-1个模块从 B 移动到  C
    }

}

int main() 
{
    int num;///要移动的盘子数
    printf("请输入要移动的盘子数:");
    scanf("%d", &num);
    hanoi(num, 'A', 'B', 'C');
    return 0;
}

运行结果如下: 

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值