C语言学习之递归
学习C语言到递归时,还记得那个用来抛砖引玉的例子: "从前呀,有座山,山里有个老和尚给一个小和尚讲故事,讲的什么故事呢?从前呀,有座山,山里有个老和尚给一个小和尚讲故事,讲的什么故事呢?从前呀......" 这个故事估计是可以说到世界毁灭 。不难发现整个故事都在循环一个语句 "从前呀,有座山,山里有个老和尚给一个小和尚讲故事,讲的什么故事呢?",那么递归的定义呢就和这差不多了。
递归: 百度百科解释为 程序调用自身的编程技巧。
利用递归,我们可以完成许多事情。比如传统的 1+2+3+4+5+......+99+100 这样的求和就可以利用递归来完成
#include"stdio.h"
//递归
int recurrence(int n)
{
if(n == 1)
return 1;
else
return recurrence(n - 1) + n;
}
int main(void)
{
printf("%d", recurrence(100));
}
说到递归,少不了著名的斐波那契数列,同样的它也是一个递归的典型例子。
- 表达式: F[n]=F[n-1]+F[n-2](n>=2,F[0]=0,F[1]=1)
由表达式,我们就可以写出对应代码
#include"stdio.h"
//斐波那契数列
int recurrence(int n)
{
if(n == 0)
return 0;
else if(n == 1)
return 1;
else
return recurrence(n - 1) + recurrence(n - 2);
}
int main(void)
{
int i;
for(i = 1; i <= 10; i ++)
printf("%d ", recurrence(i));
}
通过以上代码,就可以秒秒钟打印出斐波那契数列的前10项了,其实和 1+2+3+......+99+100没有本质上的区别。就和百度百科给出的定义一样是程序多次调用它本身。下面再举个相关的经典例子加深一下理解。
又是一个典型的粟子:
猴子第一天摘了若干个桃子,当即吃了一半,还不解馋,又多吃了一个;第二天,吃剩下的桃子的一半,还不过瘾,又多吃了一个;以后每天都吃前一天剩下的一半多一个,到第10天想再吃时,只剩下一个桃子了。问第一天共摘了多少个桃子?
相信大家都 AC 过这道例题,这猴子也是挺厉害的,第一天竟然吃了700多个桃子,Amazed...,此题不止有递归一种方法,你尽管可以用 while 、for 循环来 A.大多数递归题可以用循环来A,说白了递归本身就是循环。好像我在说废话。。。。
根据题意,可以写出对应的代码:
#include"stdio.h"
//猴子吃桃问题
int recurrence(int n)
{
if(n == 1)
return 1;
else
return 2 * (recurrence(n - 1) + 1);// 逆运算 根据题意今天的桃子加上一个再乘以二就是前一天的桃子数量
// 依次类推就可以推出10前共有多少桃子
}
int main(void)
{
printf("%d ", recurrence(10));
}
运用递归,就感觉是在套用公式。这么说递归其实很简单的,我们反过来做此题。就说猴子是摘桃,第一天摘了一个、第二天摘了前一天加一个的二倍、以后的每一天都如此,第10天后一共摘1534个桃子,问这10天每天分别有多少桃子?
不难得出,这个就是上个粟子的逆向转换而已。则相应代码如下:
#include"stdio.h"
//猴子摘桃问题
int recurrence(int n)
{
if(n == 10)
return 1534;
else
return (recurrence(n + 1) - 1) / 2;// 逆运算 根据题意今天的桃子送去一个再除以二就是明天的桃子数量
// 依次类推就可以推出10后共有多少桃子
}
int main(void)
{
int i;
for(i = 1; i <= 10; i ++)//打印列表
printf("%d ", recurrence(i));
}
只是对之前的代码进行了少许的修改,已知第10天摘了1534个桃子,那么当 i = 10 时, 返回 1534 这个值;否则是调用递归运算,递归也就是对题意进行了逆向的推算。
故做题时,先审清题意,理好思路,再动手去做就游刃有余了,递归亦如此。