假设我有一个Matrix类Matrix
,以及一个使用它进行一些计算的递归函数。特别是,heavy_computation
是一个非常昂贵的功能,我希望尽可能避免使用它。
bool heavy_computation(const Matrix& m)
{
// Expensive stuff ...
}
do_things
函数是用户调用以启动递归的顶级函数。
void do_things(const Matrix& m, std::vector<int>& collection)
{
std::vector<int> expensive_result;
if(!heavy_computation(m, expensive_result))
{
return;
}
std::cout << "New result = { ";
for(int i : expensive_result)
std::cout << i << " ";
std::cout << "}\n";
for(int i : expensive_result)
{
collection.emplace_back(i);
}
for(int j = 0; j < 3; ++j)
{
explore(m, j, expensive_result, collection);
}
}
顶级函数将工作委托给以下explore
函数。
void explore(
const Matrix& m,
int j,
const std::vector<int>& expensive_result,
std::vector<int>& collection)
{
std::cout << "j = " << j << "\n";
// Compute something based on expensive_result.
Matrix new_matrix = ...;
std::vector<int> new_expensive_result;
heavy_computation(new_matrix , new_expensive_result);
if (!new_expensive_result.empty())
{
std::cout << "New result = { ";
for (int i : new_expensive_result)
std::cout << i << " ";
std::cout << "}\n";
for (int i : new_expensive_result)
{
collection.emplace_back(i);
}
}
for (int i = 0; i < 3; ++i)
{
if (!new_expensive_result.empty())
{
explore(new_matrix, i, expensive_result, collection);
}
}
}
我想我已经盯着递归的结构太久了;它最有可能以更聪明的方式组织起来,以避免对heavy_computation
进行不必要的调用。例如,考虑程序给出的以下输出:
New result = { 9 7 8 }
j = 0
New result = { 5 0 6 }
j = 0
j = 1
j = 2
New result = { 3 1 0 }
j = 0
j = 1
j = 2
j = 1 <--- Oh no, { 5 0 6 } will be recomputed again?!
New result = { 5 0 6 }
j = 0
j = 1
j = 2
New result = { 3 1 0 }
j = 0
j = 1
j = 2
j = 2
New result = { 5 0 6 }
j = 0
j = 1
j = 2
如果我理解正确,这里的问题是当explore
返回时,heavy_computation
可以再次被调用(当然它会再次返回相同的答案,因为它是确定性的)。基本上,如果explore
给出错误,heavy_computation
的分支将被终止,否则递归会更深入。有没有办法设置do_things
和explore
,以避免对昂贵的功能进行不必要的调用?
与输出相比,我想3次调用昂贵的功能就足够了,因为我们没有更多独特的答案。
答案 0 :(得分:0)
首先,您可以在代码中改进一些内容,以便于阅读和维护。为什么要将j
传递给explore
函数?您只能将它用于打印,所以只需在调用函数之前执行此操作。
第二,这个
for (int i : new_expensive_result)
{
collection.emplace_back(i);
}
与
相同(除了更慢)collection.insert(collection.end(),
new_expensive_result.begin(), new_expensive_result.end());
第三,你的两个函数之间存在很多代码重复。您应该在发布代码之前删除它。
解决问题非常简单,真的。首先,将explore
函数拆分为两个函数:一个包含代码,包括对heavy_computation
的调用,另一个包含其余函数。递归调用现在将包含两个调用,您必须将第一个函数的一些输出传递给第二个函数。像
for (int i = 0; i < 3; ++i)
{
if (!new_expensive_result.empty())
{
std::cout << "j = " << i << "\n";
Matrix matrix_result;
std::vector<int> vector_result;
explore1(new_matrix, expensive_result, matrix_result, vector_result);
explore2(new_matrix, expensive_result, matrix_result, vector_result, collection);
}
}
现在很明显,您可以将呼叫提升到explore1
(呼叫heavy_computation
)。