部分函数的递归与迭代(非递归)实现

部分函数的递归和迭代(非递归)实现

首先,说到递归函数,大家一般都会想到斐波那契数列计算阶乘这两种,书本上大多也是以这两个为例,下面就简单介绍一下这两个吧。

斐波那契数列:

1 1 2 3 5 8......这样的数列叫做斐波那契数列,规律很简单,前两个数字的和就是第三个数字的值。
我们可以简单表示为:

            n>2    fib(n)=fib(n-1)+fib(n-2)

fib(n)

            n<=2   fib(n)=1

递归的实现代码也是比较简单的;只需要函数不断调用自身就可以了:

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

int fib_1(int n)//采用递归的方式做的
{
	if (n <= 2)
		return 1;
	else
		return fib(n - 1) + fib(n - 2);
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	printf("%d", fib_1(n));
	system("pause");
	return 0;
}

当然,这看上去很容易理解,但是,这却不是最好的方法。主要就是因为每一个递归调用都会触发另外两个递归调用,这样,冗余计算的数量增长的非常快。例如,在计算fib(10)的时候,fib(3)被调用了21次,而计算fib(30)的时候,fib(3)被计算了30多万次,这很浪费,而且效率很低。

所以,我们可以用一个简单循环来代替递归,虽然理解起来不如递归那么简单,但是效率提高了太多。


迭代的代码实现也是比较简单的,只要用一个循环,就以a,b,c三个数字举例吧,让c=a+b;得到的结果给b,再把之前b的值赋给a,这样同样实现了斐波那契数列的规律:

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

int fib_2(int n)//采用函数的方式做
{
	int i = 0;
	int a = 0;
	int b = 1;
	int c = 0;
	if (n <= 2)
		return 1;
	else
	{
		for (i = 0; i < n - 1; i++)
		{
			c = a + b;
			a = b;
			b = c;
		}
		return c;
	}
}

int main()
{
	int n = 0;
	scanf("%d", &n);
	printf("%d", fib_2(n));
	system("pause");
	return 0;
}



计算阶乘:

阶乘大家也都知道,就是一个数不断乘上自身的-1;也就是n*(n-1)*...*1。

这可以简单表示为:

             n=0    fac(n)=1

fac(n)

             n>0    fac(n)=n*fac(n-1)

递归的代码实现也是比较容易的:

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

int fac_1(int n)
{
	if (n <= 0)
	{
		return 1;
	}
	else
	{
		return n*fac_1(n - 1);
	}
}


int main()
{
	int n = 0;
	scanf("%d", &n);
	printf("%d\n", fac_1(n));
	system("pause");
	return 0;
}

当然,这和上面的斐波那契数列一样,效率很低,主要就是因为,在调用函数的时候,参数会被压到堆栈中,为局部变量分配内存空间(基本上所有的递归函数都是如此),每一的调用返回时,这些都必须还原,所以,这里产生了很大的开销。

同样的,用一个简单循环就可以完成相同的任务:

只要不断乘上自身减1就可以了,知道自身不能再减为止。

代码实现如下:

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

int fac_2(int n)
{
	int ret = 1;
	while (n > 1)
	{
		ret *= n;
		n--;
	}
	return ret;
}

int main()
{
	int n = 0;
	scanf("%d", &n);
	printf("%d\n", fac_2(n));
	system("pause");
	return 0;
}

这里代码的简洁性可以弥补递归带来的运行时开销,就上面所得调用函数时的开销。

另外,我在这里提一下用递归的方式输出数字:

以1234这个数字为例,要求屏幕上输出1 2 3 4;

代码如下:

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

void print(int num)
{
	if (num > 10)
	{
		print(num/10);//这里采用递归的方式
	}
	printf("%d ", num % 10);
}

int main()
{
	int num = 0;
	scanf("%d", &num);
	print(num);
	system("pause");
	return 0;
}

这里需要对递归有很好的理解;还是以1234为例,第一次进入函数,1234>10,那么会再次进入函数,不过是以123的大小进入,同样,123还是大于10,再次以12进入,12还是大于10,那么就再次以1进入函数,这次1<10了,那么函数就会打印1%10的结果,就是1;

接着函数调用返回,打印12%10的结果,就是2;以此类推,最后输出的结果就是4了,这样屏幕上就会显示出1 2 3 4 这样的数字了;这里就很好的演示了递归。

还有什么不足敬请提出,让我加以修改。



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值