C++ 我能以更智能的方式设置这个递归以避免调用昂贵的函数吗?

C++ 我能以更智能的方式设置这个递归以避免调用昂贵的函数吗?,c++,recursion,C++,Recursion,假设我有一个矩阵类矩阵,和一个递归函数,该函数使用它进行一些计算。特别是,重计算是一个非常昂贵的函数,我希望尽可能避免调用它 bool heavy_computation(const Matrix& m) { // Expensive stuff ... } do\u things函数是一个顶级函数,用户可以调用它来启动递归 void do_things(const Matrix& m, std::vector<int>& collection) {

假设我有一个矩阵类
矩阵
,和一个递归函数,该函数使用它进行一些计算。特别是,
重计算
是一个非常昂贵的函数,我希望尽可能避免调用它

bool heavy_computation(const Matrix& m)
{
    // Expensive stuff ...
}
do\u 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);
    }
}
我想我已经盯着递归的结构看太久了;它很可能以一种更聪明的方式组织起来,以避免对
繁重的计算进行不必要的调用。例如,考虑程序给出的下列输出:

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
newresult={978}
j=0
新结果={5 0 6}
j=0
j=1
j=2
新结果={3 1 0}
j=0
j=1
j=2

j=1首先,您可以改进代码中的一些内容,使其更易于阅读和维护。为什么要将
j
传递给
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);
        }
    }
}
第二,这个

for (int i : new_expensive_result)
{
    collection.emplace_back(i);
}
与相同(速度较慢除外)

第三,两个函数之间存在大量代码重复。在将代码发布到此处之前,您应该已删除该代码

解决你的问题很简单,真的。首先,将
explore
函数分为两个函数:一个函数包含调用
heavy_computing
之前的代码,另一个函数用于其他函数。递归调用现在将由两个调用组成,其中必须将第一个函数的一些输出传递给第二个函数。差不多

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);
    }
}
for(int i=0;i<3;++i)
{
如果(!new\u昂贵的\u result.empty())
{

std::我是否还没有详细研究过您的代码结构,但在这里是否合适?如果这是您代码的输出,则意味着
重计算
是有状态的(前两个调用获得相同的输入,但产生不同的输出)。因此,要么你不能在不查看该函数的情况下对此进行优化,要么你没有发布实际代码,浪费了我的时间。
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);
    }
}