递归入门必看——一道最简单的题搞懂递归

递归入门必看——写递归的三种方法

递归——可以认为是函数自己调用自己的一个过程

先看一道最简单的递归题——求和 1+2+3…+n=?
显然这个用循环很容易实现(从1加到n)

#include<iostream>
using namespace std;
int main() {
	int n, sum = 0;
	cin >> n;
	for (int i = 1; i <= n; i++)
		sum = sum + i;
	cout << sum;
	return 0;
}

下面用3种递归的方法实现对上述问题的求解
在这之前,再将上述问题简化一下,输出1~n。

在写一个递归函数之前,先要明确它的功能。
就这题来说,递归对i能做的操作,对i+1,i-1同样能做。

下面我要写一个递归函数 func(int i) 功能是显示 i;

#include<iostream>
using namespace std;
int n;//由于递归函数和主函数都要用n,将n定义为全局变量
void func(int i) {  //显示i,即这个函数也可以显示i+1,i-1
	if (i <= n) {
		cout << i << " ";
		fun(i + 1);
	}
}
int main() {
	cin >> n;
	func(1);
	return 0;
}

在fun(int i)中调用fun(i+1),即显示比他大1的数,使得这个函数逐项递归下去
且这个递归是从小到大实现的。因此我要显示1~n,再主函数中应该从fun(1)开始调用递归。
这里要注意的是,一定要有终止条件 if (i <= n),否则将会一直显示下去。
下面给出这个输入n=3时这个函数递归调用示意图:
尤为要注意的是,每一层传递的参数在内存中不是同一个空间
在这里插入图片描述

那在这里变一下,如果我再主函数中调用的不是func(1),而是func(n),这个递归程序该怎么改?我们很容易的想到改为以下代码:

#include<iostream>
using namespace std;
int n;//由于递归函数和主函数都要用n,将n定义为全局变量
void func(int i) {  //显示i,即这个函数也可以显示i+1,i-1
	if (i >= 1) {
		cout << i << " ";//显示功能的实现
		fun(i - 1);      //递归的实现
	}
}
int main() {
	cin >> n;
	func(n);
	return 0;
}

但是发现实现的是倒序输出3 2 1,为什么呢,在此给出递归调用示意图

在这里插入图片描述
由此我们得到启示,在写一个递归函数时,要考虑先执行这个函数功能,还是先执行递归,即要考虑功能实现与递归调用的顺序
因此,上面的func应改为

void fun(int i) {  //显示i,即这个函数也可以显示i+1,i-1
	if (i >= 1) {
		fun(i - 1);      //递归的实现
		cout << i << " ";//显示功能的实现
	}
}

即,在这个情况下,要先实现后调用的函数的功能,再实现自己的。
在这里插入图片描述

总结一下写递归预备步骤:
1.明确递归函数中参数的意义,和函数的功能
2.函数的功能实现与递归调用的次序

明白了上述微小的差异,现给出第一种实现方法:
p.s.一般我们还是习惯从1~n来实现。(上述第一种调用)

法一 全局函数法(没有返回值)

这里的函数作用是将 i 加到 sum 上
先加上 i 再调用递归,实现1+2+…+n

#include<iostream>
using namespace std;
int n;//由于递归函数和主函数都要用n,sum,将n定义为全局变量
int sum = 0;
void fun(int i) {  
	if (i <=n) {
		sum += i;
		fun(i + 1);
	}
}
int main() {
	cin >> n;
	fun(1);
	cout << sum;
	return 0;
}

注意:如果递归函数没有返回值的话,一定要有一个全局变量

法2 返回值法

这里不仅要明确func(int i)的功能,还要明确func(i)与func(i-1)的关系
函数功能:func(i)求从1到 i 的和
func(i-1)求从1到 i -1 的和
func(i)=i+func(i-1)
参数范围1<=i<=n

这里是向左边界递归故递归跳出条件为i>=1
由于函数的功能是求从1到 i 的和,求1到n的和,故调用func(n)

#include<iostream>
using namespace std;
int n;
int func(int i) {  //函数功能:求从1到i的和 func(i-1)求从1到i-1的和
	if(i>=1)
		return func(i - 1) + i;	
	return 0;
}
int main() {
	cin >> n;
	cout << func(n);
	return 0;
}

在这里为了更好的理解其内部机制,改为
在这里插入图片描述
在这里插入图片描述

若改变函数功能:func(i)是求从 i 到 n 的和(这个时候要向右边界递归了)
func(i+1)是求从 i +1到 n 的和
func(i)=i+func(i+1)
参数范围1<=i<=n
跳出条件为i<=n
由于函数的功能是求从1到 i 的和,求1到n的和,故调用func(1)

#include<iostream>
using namespace std;
int n;
//法2:返回值法
int fun(int i) {//函数是求 从i到n的和  fun(i+1)
	if(i<=n)
		return func(i + 1) + i;	
	return 0;
}
int main() {
	cin >> n;
	cout << fun(1);
	return 0;
}

在这里插入图片描述
在这里插入图片描述

法3 带参数直接传递法

int func(int i,int s) 函数中s代表从1到 i-1的和
即每次下一个函数的参数s为 i+s 直到 i 为n,即s中加了n后跳出递归
函数的功能就是把左边的参数加到右边的参数上。
不断调用 func(i+1,i+s)
1->1+s
2->2+s
3->3+s
4->跳出 return s

#include<iostream>
using namespace std;
int n;
int func(int i,int s) {  //s代表 1 到 i-1的和
	if (i <= n)
		return func(i + 1, i + s);//本质是调用,要求的结果在参数中
	return s;
}
int main() {
	cin >> n;
	cout << func(1,0);
	return 0;
}

在这里插入图片描述
下面变为s代表i+1到n的和
即每次下一个函数的参数s为 i+s 直到 i 为1,即s中加了1后跳出递归
函数的功能就是把左边的参数加到右边的参数上。
不断调用 func(i-1,i+s)
3->3+s
2->2+s
1->1+s
0->跳出 return s
但此法相当于从后往前加

#include<iostream>
using namespace std;
int n;
int func(int i,int s) {  //s代表 i+1 到 n的和
	if (i >= 1)
		return func(i - 1, i + s);//本质是调用,要求的结果在参数中
	return s;
}
int main() {
	cin >> n;
	cout << func(n,0);
	return 0;
}

在这里插入图片描述
写递归函数总结:
1.明确递归函数中参数的意义,和函数的功能(功能不同调用的机制不同)
2.函数的功能实现与递归调用的次序
3.可以通过画递归过程图帮助理解。
p.s.第三种方法不太常见,主要掌握前两种。

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值