初识递归-小白带你入门递归

开场

如标题所示,本人是正在学C的小白,这几天被递归折磨的死去活来,这里也是自己总结一下,一是作为自己的学习笔记。二也是为了帮像我一样的小白在递归上入门简单点
以下内容偏小白,大佬可以指出错误或者绕道

递归介绍

定义

什么叫递归:
在计算机中,递归是指函数或过程或子程序在运行过程序中直接或间接调用自身而产生的重入现象,即不停调用自身来解决问题。

这里按照定义写了一串代码块

#include<stdio.h>
int op(int t)
{
	op(t);//op无限调用自身
}
int main()
{
	int n;
	scanf("%d", &n);
	op(n);
	return 0;
}

这里op确实在调用自己,但是这里也发现了问题:即op无法停止对自己的调用,从而使程序陷入了死循环中(即死递归),这个问题的引出,也让我们要引入到递归实现解决问题的必要条件

必要条件

我们发现陷入死递归是因为op无法结束对自身函数调用
所以在op执行条件前,需要加上限制条件,并且在每次调用自身函数后都要慢慢接近结束递归条件

即当我们在op前加入限制条件

int op(int t)
{
	if (t > 1)
	{
		t--;
		op(t);
	}
}

在这里插入图片描述
这里也发现了程序也顺利的结束了,到这里我们就很顺利的写出了一个递归。

但是!!又有问题产生了,我们会写递归了但是还不能用它来解决的问题,而我们学递归的初衷也是为了方便解决问题,那到这不是还啥都没学吗
先别急,开始我们理解了该怎么写递归,这里我们要开始编写递归的内容来实现解决问题

编写递归

这里抛出个简单的问题,用递归来计算n的阶乘

在看到这个问题时,想要用递归来解决这个问题,就要着眼于不用递归时我们要怎样解决这个问题。
如果用迭代(可简单理解为非递归)该怎样解决?
这里会发现问题就很简单了

#include<stdio.h>
int main()
{
	int g = 1;
	int n=0;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
		g *= i;
	printf("%d", g);
	return 0;
}

构建递归关系

参照迭代实现方式发现
就是让1x2x3x……xn为止即可,但是递归思路和迭代思路不一样,递归是逆向思维
于是要将n作为参数传给函数时,想计算到n的阶乘时
首先要z=n×(n-1)再z×=(n-2),直到n等于1时便不用乘
这里我们就是构建了一个递归关系
即递归执行时应该依照n=n×(n-1)

#include<stdio.h>
int fac(int k)
{

	return k*fac(k - 1);
}
int main()
{
	int g = 1;
	int n=0;
	scanf("%d", &n);
	int g=fac(n);
	printf("%d", g);
	return 0;
}

这里实现了n的无限递归,按照前面所学
这里还需要一个限制条件来停止递归的无限循环

限制条件的设定

按照思路

首先要z=n×(n-1)再z×=(n-2),直到n等于1时便不用乘

这里发现,n=1,即为停止递归的条件,这里便可以完整代码了

#include<stdio.h>
int fac(int k)
{
	if (k > 1)
		return k * fac(k - 1);
	else
		return 1;
}
int main()
{
	int n=0;
	scanf("%d", &n);
	int g=fac(n);
	printf("%d", g);
	return 0;
}

到此为止我们成功用递归解决了一个问题。
这里不妨用两道题练练手

练手

斐波那契数列

这个问题也算是经典了,我相信大家都有所耳闻
1 1 2 3 5 8 13 21 34 55………
这里规律也十分好找即当前位置是前两位相加之和
按照我们递归的思路
首先,寻找关系式。
要计算n位斐波那契数,就要知道(n-1)+(n-2)
要计算n-1就要知道(n-2)+(n-3)
要计算n-2就要知道(n-3)+(n-4)
在这里插入图片描述
思路如图所示

这里也可以写出的关系式
n=(n-1)+(n+2)
2:明确结束条件
这里我们也能知道当n=2,n=1时我们便知道斐波那契数为1
所以当n>2时设置为结束条件是非常不错的。
到这里便可以着手写代码了

#include<stdio.h>
int print(int x)
{
	if (x > 2)//结束条件
		return print(x - 1) + print(x - 2);//关系式
	else
		return 1;
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int ret=print(n);
	printf("%d",ret);
	return 0;
}

汉诺塔

看到这个问题,相信很多人都想要点击退出了。
但是不要急,汉诺塔确实是每一个初学递归的小白的噩梦
但是看完本篇虽谈不上彻底暴砂,但也能为你提供一些思路

规则

在这里插入图片描述

计算当有n个方块时需要移动多少步

遵守思考过程,这里我们需要先了解其移动过程与规律,从而写出关系式,便于我们去编写程序
在这里插入图片描述
这里我们知道了只有一/二个方块时,需要的步数
但是程序要求我们是n个方块
这时打个比方,当n为3时,我们想知道其步数时可以运用递归方法去思考。

既然我们知道移动两个需要多少步,那就把移动三个分解,看作将两个方块移动至中间柱子,这时只需要将最下面的移动至最右边柱子,再将中将两个移动至柱子
此时我们知道移动两个是3次,则可算出需要的所有步骤为:
3(将两个移动至中间)+1(将最下面一个移动至最右侧)+3(将中间两个移动至最右侧)

如图所示
在这里插入图片描述
则当n为4时,也是同理
可看作将底部最下面一个的上面三块移动至中间柱子
将底部一块移动至最右侧
将中间三块移动至最右端柱子

而移动三个的步数可以看作一次性移动两个柱子
留下最底部的柱子
将两个柱子移动至最右侧
底部移动至中间
中间两个移动至中间
(按照这个无限套娃的思路就可以知道,要知道n个时所需步数,就要知道n-2个步数,……直到n=2时)
可画出思路图
在这里插入图片描述
通过这个思路图我们就可以写出关系式子了
f(n)=2f(n-1)+1
而限制条件就是n>2时即可,因为我们已知2个方块为3步。
下面就好编程了

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int  hannuota(int x)
{
	if (x > 2)
		return (2*hannuota(x - 1) + 1);
	else
		return 3;

}
int main()
{
	int n;
	scanf("%d", &n);
	int x=hannuota(n);
	printf("%d", x);
	return 0;
}

后记

由于是小白,技术啊,思路啊,讲题啊都有些不足之处,如果有看了不懂的地方可随时私聊或者评论询问(图也画的好丑),写的有很多不足的地方,希望大家多多海涵。

  • 7
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

想学c啊啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值