我目前正在开展处理大量递归调用的辅助项目。我不是计算机科学家,所以我不确定如何优化我的代码。我知道递归函数不是很有效,我听说你经常用尾调用替换它,但我不确定如何去做。此函数包含三个数组:appendList,sequence和used。其他参数,base,length,index和last word是整数。
function Recursion(appendList, base, length, sequence, used, lastWord, index)
#Global variables:
global G_Seq_List
global G_Seq_Index
used = ones(UInt8, 1, base^length)
used[1] = 0
if index == base^length
check = zeros(UInt8, base^length, 1)
for i = 1 : base^length
index = 1
for j = 1 : length
k = mod(i+j-1,base^length)
index = index + base^(length - j)*sequence[k+1]
end
check[index] = check[index] + 1
if check[index] != 1
return
end
end
G_Seq_List[G_Seq_Index,:] = sequence[:]
G_Seq_Index = G_Seq_Index + 1
return
end
#Builds Sequence
for i = 1 : base^length
if appendList[i , mod(lastWord - 1, base^(length - 1)) + 1] == 1
if used[i] == 1
tempUsed = used
tempUsed[i] = 0
tempCounter = index + 1
tempSequence = sequence
tempSequence[tempCounter] = mod(i - 1, base)
Recursion(appendList, base, length, tempSequence, tempUsed, i, tempCounter)
end
end
end
end
将此递归转换为尾调用是否快速解决?如果没有,我可以做些什么来优化这个功能?
答案 0 :(得分:2)
通常,任何递归都可以转换为循环,并且循环通常具有更好的性能,因为它具有类似的算法性能,而无需分配新帧并存储额外信息。
“尾部调用优化”是编译器(或运行时)所做的事情,如果递归调用是函数中的最后一次调用,则会自动将递归转换为循环(因此名称) - “尾调用”),通常通过重用相同的调用帧而不是分配新的调用帧。重用框架是可以的,因为如果你对递归调用的结果所做的只是返回它,你不需要封闭函数调用中的任何其他东西,所以没有理由让框架保持活着。
所以,你需要检查的是:
return f(...)
模式会起作用,但有时编译器可以支持更复杂的代码。两者都取决于您的特定编译器,因此我会查找有关它的文档 - 我无法分辨出您的问题是什么。