目录
前言
递归是C语言的函数章节中出现的一知识点,其理解具有一定的难度。本篇文章帮助大家更好的理解递归。
一、递归是什么?
程序自己调用自己的编程技巧就是递归。简而言之就是在一个函数在定义的同时用到了函数自身。在适合的场景,正确的运动递归,有利于让问题的简单化,然程序变得简单,大大减少代码量,实现事半功倍的效果。
在运用递归这一知识时要注意满足两个条件:
1.存在限制条件,当满足这个限制条件的时候,递归便不再继续。
2.每次递归调用之后,越来越接近这个限制条件。
public void recursion(参数0) {
if (终止条件) {
return;
}
recursion(参数1);
}
二、经典例题
1.数字拆分问题
1).数字拆分后间隔空格打印(从高位开始取数字)
根据题目要求,需要把一个多位数拆分开来,再在屏幕上打印。由于需要从高位到低位依次打印,所以就需要设法取出最高位,可以通过多次除10后再取摸运算得到。
以数字12345举例:
第一次12345进入fun1函数:n>10 n/10 第二次进入fun1函数
第二次1234 进入fun1函数:n>10 n/10 第三次进入fun1函数
第三次123 进入fun1函数:n>10 n/10 第四次进入fun1函数
第四次12 进入fun1函数:n>10 n/10 第五次进入fun1函数
第五次1 进入fun1函数:n<10
1 %10取出最高位,返回第四次
12 %10取出千位 ,返回第三次
123 %10取出百位 ,返回第二次
1234 %10取出十位 ,返回第一次
12345%10取出个位
#include<stdio.h>
void fun1(int n)
{
if (n > 10)
fun1(n / 10);
printf("%d ", n % 10);
}
int main()
{
int n = 0;
scanf("%d", &n);
fun1(n);
return 0;
}
2).数字各各位数相加(从低位开始取数字)
与上面一题原理相同,但是取数字的顺序不同,正因如此,取出的数字可以进行运算,实现求和。
#include<stdio.h>
int fun2(int n)
{
if (n < 10)
return n;
else
return n % 10 + fun2(n / 10);
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = fun2(n);
printf("%d", ret);
return 0;
}
2.青蛙跳台阶问题
问题:青蛙从第一个台阶跳到第n个台阶,一次可以跳一级台阶或者两级台阶。问青蛙跳到终点有多少钟方法?
此问题的代码书写难度不大,重要的是思路需要清晰。假设jump_frog(n)为条n级台阶的方法。
青蛙要跳n级台阶(jump_frog(n)),在刚出发时,可以跳一个台阶,剩下n-1个台阶;或者两个台阶,剩下n-2个台阶。所以跳n级台阶的问题就出现了两个分支。接下来的问题就是要求出跳n-1个台阶的方法(jump_frog(n-1))和n-2个台阶的方法(jump_frog(n-2)),求和就能得到n级的方法。不断递推,直到n=1时,有一种办法,n=2时有两种方法。
公式:jump_frog(n)=jump_frog(n-1)+jump_frog(n-2)
#include<stdio.h>
int jump_frog(int n)
{
if (n == 1)
return 1;
else if (n == 2)
return 2;
else
return jump_frog(n - 1) + jump_frog(n - 2);
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = jump_frog(n);
printf("%d", ret);
return 0;
}
此问题和斐波那契数列问题的原理是一样的,只不过递归刚开始的数据有所差异 。
3汉罗塔问题
问题:有三根柱子,把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。问最终完成要多少步。
Tower_of_Hanoi(n)表示n个圆盘完成汉罗塔问题的步数。
从根本上来讲,需要把n个圆盘上的n-1圆盘放到一根柱子上(Tower_of_Hanoi(n-1)),再把最后第n个圆盘放到目标的柱子上(1步),最后把n-1个圆盘在放回到目标柱子上(Tower_of_Hanoi(n)),就完成了求解。而问题就变成了要解决如何移动n-1个圆盘,答案便是对n-2个圆盘(Tower_of_Hanoi(n-2))进行重复上文的操作。如此就可以从中看出递归的影子。最后逆推到只有一个圆盘,只需要一步可完成,两个圆盘是三步可以完成。
公式:Tower_of_Hanoi(n)=2*Tower_of_Hanoi(n-1)+1
#include<stdio.h>
int Tower_of_Hanoi(int n)
{
if (n == 1)
return 1;
else
return 2 * Tower_of_Hanoi(n - 1) + 1;
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = Tower_of_Hanoi(n);
printf("%d", ret);
return 0;
}
三、注意事项
1.在使用递归时,要注意程序设计时不能忽视限制条件和向条件逼近。由于每次调用都要在栈区中开辟新的空间,如果死递归会造成栈溢出导致程序崩溃。
2.类似斐波那契数列,青蛙跳台阶等,公式是通过前面多选运算后得到所求项的这一类题目——列fun(n)=fun(n - 1) + fun(n - 2),如果需要求得的项数较大,会由于数据的重复计算使得效率底下,建议通过循环来实现。
3.递归能实现的程序,绝大多数情况下循环也能够实现。反之则不成立。
总结
递归的学习需要自身多对他进行实践,静心感悟经典例题中的原理,对其总结,加深了解深度,才能在日后写程序时把他同好,成为一个得心应手的工具。