函数的递归与迭代

1. 递归是什么?

递归是学习C语⾔函数绕不开的⼀个话题,那什么是递归呢? 递归其实是⼀种解决问题的⽅法,在C语⾔中,递归就是函数⾃⼰调⽤⾃⼰。“递”的意思是递推,“归”意思是回归。这样解释不太好理解,下面举例。

前置打印

下面我们首先举出一个例子:实现一个函数print1,功能是接收一个整形数据,打印此整形的每一位的数字,比如输入15867,就打印1 5 8 6 7。

void print1(int num)
{
	if (num < 10)
	{
		printf("%d ", num);
	}
	else
	{
		print1(num / 10);
		printf("%d ", num%10);
	}
	
}

就拿刚才15867的例子,先判断大于还是小于10,15867显然执行else部分的代码,于是15867就分解成1586和7,1586作为一个新的参数输入进print1函数,1586又分解成158和6.......以此类推。

但需要注意的是,这里属于后置打印,就是在“回归”的时候进行打印,printf放在print1的后面,所以说在递推的时候是不进行打印的。

后置打印

为了深层次地感受“递推”与“回归”,我又写了print2函数,功能与print1函数一样,但此次用的是前置打印,也就是在递推的时候就打印。

//判断数字是几位数的函数
int count(int x)
{
	int t = 0;
	while (x!=0)
	{
		x /= 10;
		t++;
	}
	return t;

}


void print2(int num)//这是前置打印,递推时的打印
{
	//判断num是几位数
	
	if (num < 10)
	{
		printf("%d ", num);
	}
	else
	{
		int a = count(num);
		int b = pow(10, a-1);
		
		printf("%d ", num / b);
		print2(num % b);
	}
	
}

首先我先定义了一个函数count用于计算输入的整形的位数。又是15867的例子,int a是15867的位数,也就是5,b此时是10000,15864/10000得到的1就是第一位的数字,显然将15867分解成1和5867.所以这里的1是要最先打印的,5是第二个打印的。因此前置打印。

来看一下完整的代码:

#define _CRT_SECURE_NO_WARNINGS 1	
#include<stdio.h>
#include<math.h>

void print1(int num)//这是后置打印,回归时的打印
{
	if (num < 10)
	{
		printf("%d ", num);
	}
	else
	{
		print1(num / 10);
		printf("%d ", num%10);
	}
	
}
//判断数字是几位数的函数
int count(int x)
{
	int t = 0;
	while (x!=0)
	{
		x /= 10;
		t++;
	}
	return t;

}


void print2(int num)//这是前置打印,递推时的打印
{
	//判断num是几位数
	
	if (num < 10)
	{
		printf("%d ", num);
	}
	else
	{
		int a = count(num);
		int b = pow(10, a-1);
		
		printf("%d ", num / b);
		print2(num % b);
	}
	
}


int main()
{
	print1(13579);
	printf("\n");
	print2(1345);
}

执行成果

2.函数递归中的数学思想

函数的递归实质上运用了数学中的“数学归纳法”,我们首先要直到n=1(,n=2)时的函数值,然后根据递推的规律一项一项地往后推,这种方法极大有的时候地简化了代码,使⽤了⼤事化⼩的思路。我们来实现斐波那契数列。

#define _CRT_SECURE_NO_WARNINGS 1	
#include <stdio.h>
int count = 0;
int Fib(int n)
{
	
	if (n <= 2)
		return 1;
	else
		return Fib(n - 1) + Fib(n - 2);
}
int main()
{
	int a = Fib(20);
	printf("%d", a);
}

这里的代码很好解释,就不进行详细解释。我们可以看到此代码仅仅几行就描述出斐波那契数列,十分简洁,但还是要提醒一点,函数的递归虽然简化了代码,但是并不意味着提高了运行效率。

我们试着将先前的20改成50,会发现电脑一直计算不出这个数字,原因时重复的计算太多,导致效率极其低。而根据我们正常人的思维,第50位似乎并没有如此难计算。

int main()
{
	int a = Fib(50);
	printf("%d", a);
}

3.递归虽好,可别忘了迭代

#define _CRT_SECURE_NO_WARNINGS 1	
#include <stdio.h>
int count = 0;
int Fib(int n)
{
	int a = 1;
	int b = 1;
	int c = 1;
	while (n > 2)
	{
		c = a + b;
		a = b;
		b = c;
		n--;
	}
	return c;
}
int main()
{
	int a = Fib(20);
	printf("%d", a);
}

这个迭代的代码就非常符合人们正常的思路,避免了重复的计算,其中c相当于fib(n),a和b相当于fib(n-1),fib(n-2)。每执行一次循环,b->a,c->b,然后c重新进行计算,相当于三个变量同时往后移动了一位。极大的提高了代码的运行效率。

由于编者水平有限,缺点和疏漏在所难免,恳请大家不吝指正,万分感激。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值