撤消递归树

时间:2015-08-02 20:17:51

标签: c++ optimization recursion memoization

简短我应该如何减少(优化)代码中所需操作的数量?

LONGER 为了研究,我在C ++中编写了一组方程,如果它适合模型,则输出一个序列。在代码的内部是这个函数,在运行时被称为多次:

int Weight(int i, int q, int d){
    int j, sum = 0;
    if (i <= 0)
        return 0;
    else if (i == 1)
        return 1;
    for (j = 1; j <= d; j++){
        sum += Weight((i - j), q, d);
    }
    sum = 1 + ((q - 1) * sum);
    return sum;
}

因此,基于变量d的大小,索引i的大小,以及在其余代码中调用此函数的次数,可以完成许多冗余计算。我该如何减少计算次数?

理想情况下,例如,在计算Weight(5, 3, 1)之后,当我调用Weight(6, 3, 1)时,我如何告诉计算机替换其值而不是重新计算其值,因为该函数是递归定义的?

在这种情况下,多维向量是否可以存储值?我应该只将值打印到要读取的文件中吗?我还没有遇到输入大小I溢出的溢出,但是尾递归有助于优化吗?

注意:我还在学习如何编程,我很惊讶我甚至可以在第一时间获得该模型。

2 个答案:

答案 0 :(得分:3)

您可以使用memoization

int WeightImpl(int i, int q, int d); // forward declaration

// Use memoization and use `WeightImpl` for the real computation
int Weight(int i, int q, int d){
    static std::map<std::tuple<int, int, int>, int> memo;

    auto it = memo.find(std::make_tuple(i, q, d));
    if (it != memo.end()) {
        return it->second;
    }
    const int res = WeightImpl(i, q, d);
    memo[std::make_tuple(i, q, d)] = res;
    return res;
}

// Do the real computation
int WeightImpl(int i, int q, int d){
    int j, sum = 0;
    if (i <= 0)
        return 0;
    else if (i == 1)
        return 1;
    for (j = 1; j <= d; j++){
        sum += Weight((i - j), q, d); // Call the memoize version to save intermediate result
    }
    sum = 1 + ((q - 1) * sum);
    return sum;
}

Live Demo

注意:当您使用递归调用时,您必须谨慎调用哪个版本来实际记忆每个中间计算。我的意思是应该修改递归函数以不调用自身,而是调用函数的memoize版本。对于非递归函数,可以在不修改实际函数的情况下完成memoization。

答案 1 :(得分:0)

您可以使用数组来存储中间值。例如,某些d和q的数组包含索引i处的权重(i,q,d)。

如果将数组项初始化为-1,则可以在函数中执行,例如

if(sum_array[i] != -1){    // if the value is pre-calculated
    sum += sum_array[i];
}
else{
    sum += Weight((i - j), q, d);
}