撤消递归树
Undoing a recursion tree
SHORT我应该如何减少(优化)代码中所需操作的数量?
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)
时,我如何告诉计算机替换它的值而不是重新计算它的值?
在这种情况下,多维向量是否可以存储值?我应该把这些值打印到一个要读取的文件中吗?我还没有遇到我给它的输入大小溢出,但是尾部递归是否有助于优化它?
注意:我仍然在学习如何编程,我很惊讶我甚至能够在第一个地方得到正确的模型。
你可以使用记忆法
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;
}
现场演示
注意:在使用递归调用时,必须谨慎选择调用哪个版本才能真正记住每个中间计算。我的意思是递归函数应该被修改为不调用它自己,而是调用函数的记忆版本。对于非递归函数,可以在不修改实函数的情况下进行记忆。
可以使用数组来存储中间值。例如,对于特定的d和q有一个数组,其中包含索引为i的Weight(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);
}
相关文章:
- 通过递归进行因子分解
- 递归函数计算序列中的平方和(并输出过程)
- 使用递归的数组的最小值.这是怎么回事
- 递归列出所有目录中的C++与Python与Ruby的性能
- 递归计数给定目录的文件和所有目录
- 如何在BST的这个简单递归实现中消除警告
- C++:正在检查LinkedList中的回文-递归方法-错误
- 递归模板化函数不能分配给具有常量限定类型"const tt &"的变量"state"
- 递归无序映射
- TSP递归解的迭代形式
- 如何在Elixir中调用递归函数并行
- 返回递归调用和仅递归调用的区别
- 数组元素打印的递归方法
- 使用递归时获取变量的奇怪值
- 如何在C++中递归地按相反顺序打印集合
- 到连接组件算法的问题(递归)
- 如何使用递归打印修改后的星号三角形图案
- 使用递归模板动态分配的多维数组
- 递归函数有效,但无法记忆
- 撤消递归树