递归与非递归之间的比较
为了研究递归与非递归的区别,两者都有什么优缺点,下面我们以“斐波那契数列”和“n!问题”来研究上述问题。
目录
一、n!问题
我们先将n!问题的递归与非递归方式进行代码复现(均只展示功能函数部分):
1、递归法
int fac(int n)
{
int f;
if(n<0)
{
printf("error");
}
else if(n==0||n==1)
{
f=1;
}
else
{
f=fac(n-1)*n;
}
return f;
}
2、非递归法
int fac(int n)
{
int i,f=1;
if (n == 0 || n == 1)
{
return 1;
}
else
{
for (i = 1; i <= n; i++)
{
f = f*i;
}
return f;
}
}
在测试程序功能正常后,利用百位循环对程序进行测试。具体操作为:测试不同类型的函数可以得到的最大项的值和项数以及运行耗时进行研究。
4、结果展示
递归 | 非递归 | ||||||
类型 | 最大项 | 正确值 | 运行时间 | 类型 | 最大项 | 正确值 | 运行时间 |
int类型 | 12 | 479001600 | 0.023 | int类型 | 12 | 479001600 | 0.022 |
Float 类型 | 13 | 6227020800 | 0.021 | Float 类型 | 13 | 6227020800 | 0.023 |
long 类型 | 12 | 479001600 | 0.021 | long 类型 | 12 | 479001600 | 0.021 |
long long 类型 | 20 | 2432902008176640000 | 0.023 | long long 类型 | 20 | 2432902008176640000 | 0.022 |
Double 类型 | 22 | 1124000727777607680000 | 0.022 | Double 类型 | 22 | 1124000727777607680000 | 0.025 |
5、分析
首先,我们先来看一下n!的递归函数:
使用递归的方式进行n!的运算就是将上述函数进行代码复现,这种操作是十分简便的。
求fac(n),就是求解fact(n-1)*n;求fac(n-1),就是求fac(n-2)*n......以此类推,直到推到fac(1)完成计算。这种递归的计算方法容易理解,代码复用率高,程序运行的时间一般偏长(因为每一次计算都需要经过一次次的计算前一个函数所得值)
非递归方法则是直接上循环,从n=1一直循环到所要求阶乘的数。从而得到要求的结果,简单粗暴,却很有效果。
二、斐波那契数列
1、 递归法
int fib(int n)
{
if(n==1||n==2)
{
return 1;
}
else
{
return fib(n-1)+fib(n);
}
}
2、非递归法
int fib(int n)
{
if(n == 0)
return 0;
if(n == 1 || n == 2)
return 1;
int a=1,b=1,c=0;
for(int i=3;i<=n;i++)
{
c = a+b;
a = b;
b = c;
}
return c;
}
3、测试部分
在测试程序功能正常后,利用百位循环对程序进行测试。具体操作为:测试不同类型的函数可以得到的最大项的值和项数以及运行耗时进行研究。
4、结果展示
递归 | 非递归 | ||||||
类型 | 最大项 | 正确值 | 运行时间 | 类型 | 最大项 | 正确值 | 运行时间 |
Int 类型 | 46 | 1836311903 | Int 类型 | 46 | 1836311903 | 0.022 | |
Float 类型 | 36 | 14930352 | Float 类型 | 36 | 14930352 | 0.02 | |
long 类型 | 46 | 1836311903 | long 类型 | 46 | 1836311903 | 0.022 | |
long long 类型 | 92 | 7540113804746346429 | long long 类型 | 92 | 7540113804746346429 | 0.027 | |
Double 类型 | 78 | 8944394323791464 | Double 类型 | 78 | 8944394323791464 | 0.029 |
5、分析
首先,我们给出斐波那契数列的推导公式:
使用递归的方式进行斐波那契数列的运算就是将上述函数进行代码复现,这种操作是十分简便的。
非递归法进行斐波那契数列运算,即在进行n次循环后得到结果。
Python中的斐波那契数列问题和n!问题
一、n!问题
1、递归法
import time
def fac(n):
if n<0:
print("error")
elif n==0 or n==1:
return 1
else:
return fac(n-1)*n
def main():
a=time.time()
for i in range(1,101):
fac(i)
print(fac(i)) # print("\n")
b=time.time()
print("running time:%s Seconds"%(b-a))
main()
2、非递归法
import time
def factorial(n):
result = n
for i in range(1,n):
result *=i
return result
def main():
a=time.time()
for i in range(1,101):
print(factorial(i))
b=time.time()
print("running time:%s Seconds"%(b-a))
main()
二、斐波那契数列
1、递归法
import time
def Fibonacci(i):
if i==0:
return 0
elif i==1:
return 1
else:
return Fibonacci(i-1)+Fibonacci(i-2)
def main():
a=time.time()
for i in range(1,101):
print(Fibonacci(i))
b=time.time()
print("running time:%s Seconds"%(b-a))
main()
2、非递归法
import time
def fib(n):
if n<=0:
return 0
if n == 1:
return n
first, second, third = 0, 1, 0
for i in range(2, n+1):
third = first + second
first = second
second = third
return third
def main():
a=time.time()
for i in range(1,101):
print(fib(i))
b=time.time()
print("%s"%(b-a))
main()
三、结果展示
递归 | 非递归 | ||||||
名称 | 第几项 | 正确值 | 运行时间 | 名称 | 第几项 | 正确值 | 运行时间 |
n! | 100 | 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000 | 0.0028 | n! | 100 | 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000 | 0.0059 |
斐波那契数列 | 100 | 354224848179261915075 | 无法计算 | 斐波那契数列 | 100 | 354224848179261915075 | 0.00432 |
总结:
递归的好处:代码相对非递归来说,更简洁,并且思路清晰。思路清晰,可读性强。
递归的坏处:消耗空间要比非递归大。如果递归深度太深,可能会导致系统奔溃。
非递归的优点:效率高,执行时间只会因为循环的次数增加而增加。
非递归的缺点:不太容易理解,编写复杂问题时比较困难。
在很多情况下,只要有数学公式的支持,递归算法通常很容易解决问题。