草庐IT

C语言递归及经典例题详解

fun- 2023-11-05 原文

 什么是递归?

什么时候使用递归

例题1 顺序打印问题

例题2 求n的阶乘

例题3 求第n个斐波那契数

经典 汉诺塔问题

经典 青蛙跳台阶问题 

什么是递归?

递归就是程序调用自身的编程技巧。递归通常把一个大型复杂的问题层层转化为一个与原问题相似,规模较小的问题来求解。递归策略只需要少量的程序就可以描述出解题过程所需要的多次重复的计算,大大减少程序的代码量。

递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。

什么时候使用递归?

1、大问题可以拆分成若干小问题。

2、原问题与子问题除数据规模不同,求解思路完全相同。

3、存在递归终止条件。

4、当不满足终止条件时,要如何缩小函数值,并让其进入下一层循环中。

例题1 顺序打印问题:

输入一个整数123,依次在屏幕打印1 2 3 

代码:

#include <stdio.h>
void print(int n)
{
	if (n > 10)
	{
		print(n / 10);
	}
	printf("%d ", n%10);
}
int main()
{
	int n = 0;
	scanf_s("%d", &n);
	print(n);
	return 0;
}

例题分析:本题的思路不断拆分整数,并将他们一一打印,只要n>10,就另n不断除以10,不断的递归调用n/10,当n<10时,满足递归终止条件,令n%10,此时我们得到的是此数的最高位。当打印完最高位时返回,继续打印不一定是个位数,所以%10只保留个位。

例题2 求n的阶乘:

代码:

int Fac(int n)
{
	if (n == 1)
	{
		return 1;
	}
	return n*Fac(n - 1);
}
int main()
{
	int n = 0;
	scanf_s("%d", &n);
	int ret = Fac(n);
	printf("%d", ret);
	return 0;
}

例题分析: 求n!就是不断求n*(n-1)的过程,而这个过程又分为2种情况,当n=1时,n!=1;当n>1时,n!=n*Fac(n-1)。我们求Fac(n),就是不断求Fac(n-1)的过程,当不断递归求到Fac(1)时,依次计算阶乘返回,最终得到n!

例题3 求斐波那契数列

求第n个斐波那契数

代码:

int Fib(int n)
{
	if (n <= 2)
	{
		return 1;
	}
	return Fib(n - 1) + Fib(n - 2);
}
int main()
{
	int n = 0;
	scanf_s("%d", &n);
	int ret = Fib(n);
	printf("%d", ret);
	return 0;
}

例题分析:斐波那契数列就是前两个数为1,从第3个数开始,所有数都为前两个数的和。这样的话我们可以分成两种情况,一种是n<=2时,第n个斐波那契数的值为1;当n>2时,第n个斐波那契数的值为Fib(n-1)+Fib(n-2)。

经典 汉诺塔问题:

该问题的主要材料包括三根高度相同的柱子和一些大小及颜色不同的圆盘,三根柱子分别为起始柱A,辅助柱B及目标柱C。

操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于任意杆上。

问题分析:为了便于理解,我们首先分析3个盘子的移动过程:

1、将A柱上的两个盘子移动到B柱(借助C)

2、将A柱上的一个盘子移动到C柱

3、将B柱上的2个盘子移动到C柱(借助A)

其中,第2步直接将最大盘放到C柱可直接实现。

第1步又可以分解为:

1.1 将A柱上的一个盘子移动到C

1.2 将A柱上的第二个盘子移动到B

1.3 将C柱上的盘子移动到B

 

第3步又可以分解为:

3.1 将B柱的第一个盘子移动到A柱

3.2 将B柱的第二个盘子移动到C柱

3.3 将A柱的一个盘子移动到C柱

 综上可以得到3个盘子的移动步骤:

A->C

A->B

C->B

A->C

B->A

B->C

A->C

以上3个盘子移动共经历了7步完成。

从这里我们可以推出规律:如果有n个盘子移动,一共会经历2^n-1步。 

所以如何移动n个盘子呢?

道理和3个盘子移动是一样的,移动过程如下:

1、将A柱上的n-1个盘子移动到B柱(借助C)

2、将A柱上的一个盘子移动到C柱

3、将B柱上的n-1个盘子移动到C柱(借助A)

代码: 

#include <stdio.h>
void move(char x, char y)
{
	printf("%c-->%c\n", x, y);
}
void hanoi(int m, char one, char two, char three)
{
	if (m == 1)
	{
		move(one, three);
	}
	else
	{
		hanoi(m - 1, one, three, two);
		move(one, three);
		hanoi(m - 1, two, one, three);
	}
}
int main()
{
	int m = 0;
	printf("请输入移动盘子的数量:>\n");
	scanf_s("%d", &m);
	hanoi(m, 'A', 'B', 'C');
	return 0;
}

移盘方案:

经典 青蛙跳台阶问题: 

一只青蛙一次可以跳上一级台阶,也可以跳上2级,求该青蛙跳上n级的台阶总共有多少种跳法(先后次序不同算不同结果)。

例题分析:此题可以分为台阶有1,2,3....n级台阶。

台阶为1级时:有1种跳法

台阶为2级时:有2种跳法

台阶为3级时:有3种跳法

台阶为4级时:有5种跳法

........

台阶为n级时:有(n-1)+(n-2)种跳法

代码:

int jumpFloor(int m)
{
	if (m == 1)
	{
		return 1;
	}
	else if (m == 2)
	{
		return 2;
	}
	else
	{
		return jumpFloor(m - 1) + jumpFloor(m - 2);
	}
}
int main()
{
	int target = 0;
	printf("请输入青蛙所要跳的台阶数:>\n");
	scanf_s("%d", &target);
	int ret = jumpFloor(target);
	printf("%d\n", ret);
	return 0;
}

感谢阅读,欢迎大家批评指正!

有关C语言递归及经典例题详解的更多相关文章

  1. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  2. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  3. Unity 热更新技术 | (三) Lua语言基本介绍及下载安装 - 2

    ?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------

  4. 7个大一C语言必学的程序 / C语言经典代码大全 - 2

    嗨~大家好,这里是可莉!今天给大家带来的是7个C语言的经典基础代码~那一起往下看下去把【程序一】打印100到200之间的素数#includeintmain(){ inti; for(i=100;i 【程序二】输出乘法口诀表#includeintmain(){inti;for(i=1;i 【程序三】判断1000年---2000年之间的闰年#includeintmain(){intyear;for(year=1000;year 【程序四】给定两个整形变量的值,将两个值的内容进行交换。这里提供两种方法来进行交换,第一种为创建临时变量来进行交换,第二种是不创建临时变量而直接进行交换。1.创建临时变量来

  5. Hive SQL 五大经典面试题 - 2

    目录第1题连续问题分析:解法:第2题分组问题分析:解法:第3题间隔连续问题分析:解法:第4题打折日期交叉问题分析:解法:第5题同时在线问题分析:解法:第1题连续问题如下数据为蚂蚁森林中用户领取的减少碳排放量iddtlowcarbon10012021-12-1212310022021-12-124510012021-12-134310012021-12-134510012021-12-132310022021-12-144510012021-12-1423010022021-12-154510012021-12-1523.......找出连续3天及以上减少碳排放量在100以上的用户分析:遇到这类

  6. ruby - 递归地将所有数字字符串转换为 Ruby 哈希中的整数 - 2

    我有一个随机大小的散列,它可能有类似"100"的值,我想将其转换为整数。我知道我可以使用value.to_iifvalue.to_i.to_s==value来做到这一点,但我不确定我将如何在我的散列中递归地做到这一点,考虑到一个值可以是一个字符串,或一个数组(哈希或字符串),或另一个哈希。 最佳答案 这是一个非常简单的递归实现(尽管必须同时处理数组和散列会增加一些技巧)。deffixnumifyobjifobj.respond_to?:to_i#IfwecancastittoaFixnum,doit.obj.to_ielsifobj

  7. Ruby:标准递归模式 - 2

    我经常迷上ruby​​的一件事是递归模式。例如,假设我有一个数组,它可能包含无限深度的数组作为元素。所以,例如:my_array=[1,[2,3,[4,5,[6,7]]]]我想创建一个方法,可以将数组展平为[1,2,3,4,5,6,7]。我知道.flatten可以完成这项工作,但这个问题是作为我经常遇到的递归问题的一个例子-因此我试图找到一个更可重用的解决方案。简而言之-我猜这种事情有一个标准模式,但我想不出任何特别优雅的东西。任何想法表示赞赏 最佳答案 递归是一种方法,它不依赖于语言。您在编写算法时要考虑两种情况:再次调用函数的情

  8. ruby - 如何保持我不常用的编程语言技能 - 2

    关闭。这个问题是off-topic.它目前不接受答案。想改进这个问题吗?Updatethequestion所以它是on-topic用于堆栈溢出。关闭11年前。Improvethisquestion我不经常使用ruby​​-通常它加起来相当于每两个月或更长时间编写一次脚本。我的大部分编程都是使用C++进行的,这与ruby​​有很大不同。由于我与ruby​​之间的差距如此之大,我总是忘记语言的基本方面(比如解析文本文件和其他简单的东西)。我想每天练习一些基本的东西,我想知道是否有一些我可以订阅的网站,并且会向我发送当天的Ruby问题或类似的东西。有人知道这样的站点/Internet服务吗?

  9. ruby-on-rails - 如果特定语言环境中缺少翻译,如何配置 i18n 以使用 en 语言环境? - 2

    如果特定语言环境中缺少翻译,如何配置i18n以使用en语言环境翻译?当前已插入翻译缺失消息。我正在使用RoR3.1。 最佳答案 找到相似的question这里是答案:#application.rb#railswillfallbacktoconfig.i18n.default_localetranslationconfig.i18n.fallbacks=true#railswillfallbacktoen,nomatterwhatissetasconfig.i18n.default_localeconfig.i18n.fallback

  10. ruby - 为什么我用递归得到 "stack level too deep"? - 2

    我有这个ruby代码:defget_sumnreturn0ifn似乎正在为999之前的值工作。当我尝试9999时,它给了我这个:stackleveltoodeep(SystemStackError)所以,我添加了这个:RubyVM::InstructionSequence.compile_option={:tailcall_optimization=>true,:trace_instruction=>false}但什么也没发生。我的ruby版本是:ruby1.9.3p392(2013-02-22revision39386)[x86_64-darwin12.2.1]我还增加了机器的堆栈大

随机推荐