优化递归函数

时间:2017-04-26 20:14:30

标签: recursion optimization tail-recursion

我目前正在开展处理大量递归调用的辅助项目。我不是计算机科学家,所以我不确定如何优化我的代码。我知道递归函数不是很有效,我听说你经常用尾调用替换它,但我不确定如何去做。此函数包含三个数组: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

将此递归转换为尾调用是否快速解决?如果没有,我可以做些什么来优化这个功能?

1 个答案:

答案 0 :(得分:2)

通常,任何递归都可以转换为循环,并且循环通常具有更好的性能,因为它具有类似的算法性能,而无需分配新帧并存储额外信息。

“尾部调用优化”是编译器(或运行时)所做的事情,如果递归调用是函数中的最后一次调用,则会自动将递归转换为循环(因此名称) - “尾调用”),通常通过重用相同的调用帧而不是分配新的调用帧。重用框架是可以的,因为如果你对递归调用的结果所做的只是返回它,你不需要封闭函数调用中的任何其他东西,所以没有理由让框架保持活着。

所以,你需要检查的是:

  1. 您的编译器是否支持尾调用优化。
  2. 为了让编译器能够这样做,你必须做什么 - 通常直截了当的return f(...)模式会起作用,但有时编译器可以支持更复杂的代码。
  3. 两者都取决于您的特定编译器,因此我会查找有关它的文档 - 我无法分辨出您的问题是什么。