最初,所有的gtdch代码都是递归编写的。 递归有很多缺点,执行效率低,浪费资源,可能导致堆栈溢出。 递归程序的优点也很明显,但结构层次清晰,容易理解。
可以使用循环方式来代替递归,当然也可以使用末尾递归方式。
尾部递归是指从末尾开始计算,即使每次递归都有适当的结果,也就是说函数调用出现在调用函数的末尾。 因为是末尾,所以不需要保存局部变量。 直接使被调用的函数在返回时越过调用方返回到调用方。 尾部递归是指将当前运算结果(或路径)放入参数中传递给下级函数。 深层函数面临的不是越来越简单的问题,而是越来越复杂的问题。 因为自变量带有前一步的运算路径。 末尾递归极其重要,如果不使用末尾递归,函数的栈消耗无法估量,需要保存很多中间函数的栈。 递归程序需要存储以前n步操作的所有状态,这需要大量资源,但对于尾部递归来说并不需要。 末尾递归是一种编程技巧。 在递归函数中,如果递归调用返回的结果总是直接返回,则称为尾部递归。 末尾递归的函数有助于将算法转换为函数编程语言,从编译器的角度也容易进行优化使其成为通常的循环。 这是因为,从计算机的基本面来说,所有的循环都是通过跳转到重复代码的开头来实现的。 如果有末尾递归,只需要将堆栈重叠。 计算机只需要更改函数的参数,然后重新调用
为了加深末尾递归、递归、循环的对比,这里给出gtdch数列的实现例子:
# #! 美国航空/日本航空/日本航空
# #编码: utf-8
' ' ' '
沂水寒城
功能:末尾递归
''''
导入时间
effib_recursion(num ) :
''''
用递归法直接求gtdch数的第num个数字
''''
if num2:
返回号
返回光纤通道(编号-1)光纤通道(编号-2) )。
def fib _ tail _ recursion (编号、精度、时间) :
''''
用末尾递归法求gtdch数的第num个数字
''''
if号==0:
返回者
else:
返回光纤通道(编号1,临时,临时) )。
def光纤通道(编号) :
''''
直接使用循环求解
''''
a=0
b=1
财富(1,编号) :
丙=甲乙
a=b
b=c
返回c
if __name__=='__main__':
num _ list=[ 5,10,20,30,40,50 ]
编号列表:
开始_时间=时间.时间(
打印光纤识别(编号)
end_time=time.time (
printf IB _ tail _ recursion ((数字,0,1 ) ) ) ) ) ) ) ) ) ) ) ) ) ) )。
end_time2=time.time (
printf IB _ circle (数字) )。
end_time3=time.time (
打印正在解析的gtdch数字的后缀是%s' %num
打印'直接递归需要',结束_时间-开始_时间
打印'末尾递归调用需要一段时间是',end_time2-end_time
打印的直接使用循环时间为',结束时间3 -结束时间2
结果如下。
5
5
5
正在解的gtdch的数字的后缀是5
递归所需时间为6.38961791992e-05
递归调用需要2.31266021729e-05小时
直接使用循环时间为1.97887420654e-05
55
55
55
正在解的gtdch的数字的后缀是10
递归所需的时间为6.60419464111e-05
递归调用需要3.31401824951e-05小时
直接使用循环时间为1.8835067749e-05
6765
6765
6765
正在解的gtdch的数字的后缀是20
递归所需的时间为0.00564002990723
递归调用需要3.09944152832e-05小时
直接使用循环时间为2.09808349609e-05
832040
832040
832040
正在解的gtdch的数字的后缀是30
递归所需的时间为0.39971113205
递归调用需要1.69277191162e-05小时
直接使用周期时间为1.19209289551e-05
102334155
102334155
102334155
正在解的gtdch的数字的后缀是40
递归所需的时间为39.0365440845
递归调用需要2.19345092773e-05小时
直接使用周期时间为1.78813934326e-05
12586269025
12586269025
12586269025
正在解决的gtdch数字的后缀是50
递归所需的时间为4915.68643498
递归调用需要2.19345092773e-05小时
直接使用循环时间为2.09808349609e-05
绘制图表后,可以看得更清楚。