递归的经典题型

目录

前言

二、经典例题

1.数字拆分问题

1).数字拆分后间隔空格打印(从高位开始取数字)

2).数字各各位数相加(从低位开始取数字)

2.青蛙跳台阶问题

3汉罗塔问题

三、注意事项

总结


前言

递归是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
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;
}

递归的经典题型_第1张图片

2).数字各各位数相加(从低位开始取数字)

 与上面一题原理相同,但是取数字的顺序不同,正因如此,取出的数字可以进行运算,实现求和。

#include
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
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
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.递归能实现的程序,绝大多数情况下循环也能够实现。反之则不成立


总结

递归的学习需要自身多对他进行实践,静心感悟经典例题中的原理,对其总结,加深了解深度,才能在日后写程序时把他同好,成为一个得心应手的工具。

你可能感兴趣的:(C语言,c语言)