递归在C ++中真的很慢吗?

时间:2014-04-23 05:52:54

标签: c++ performance recursion

我知道在某些语言中递归很快(甚至比迭代更快)。但我在谈论C ++(也许C也是一样)。

我正在解决在线法官问题(不是家庭作业)。我使用自顶向下的动态编程方法解决了这个问题。但我最后2个案件得到了TLE。然后,我使用自下而上的方法,解决方案被接受。但是,在这个问题中,我认为自上而下应该更快,因为可以进行优化以跳过一些不计算的状态。

问题陈述:http://www.hkoi.org/training2004/files/need-for-speed.pdf

代码如下:

#include <cstdio>
#include <algorithm>

using namespace std;

int n, max_t; 
int num[51][50001];
int ts[50][50];
int ms[50];
int ls[50];

#ifdef RECURSION
int solve(int rn, int tleft)
{
    if (rn >= n)
        return 0;

    if (num[rn][tleft] != -1)
        return num[rn][tleft];

    int t;
    int max_num = solve(rn + 1, tleft);
    for (int i = rn; i < n; ++i)
    {
        t = ls[i];
        for (int j = 0; j < ms[i]; ++j)
        {
            t += ts[i][j];
            if (t > tleft)
                break;

            max_num = max(max_num, solve(i + 1, tleft - t) + j + 1);
        }
    }

    num[rn][tleft] = max_num;
    return max_num;
}
#endif

int main()
{
    scanf("%d %d", &n, &max_t);

    for (int i = 0; i < n; ++i)
    {
        scanf("%d %d", ls + i, ms + i);

        for (int j = 0; j < ms[i]; ++j)
        {
            scanf("%d", ts[i] + j);
        }

        sort(ts[i], ts[i] + ms[i]);
    }

    for (int i = 0; i <= n; ++i)
    {
        for (int j = 0; j <= max_t; ++j)
        {
            #ifdef RECURSION
            num[i][j] = -1;
            #else
            num[i][j] = 0;
            #endif
        }
    }

    #ifdef RECURSION
    printf("%d\n", solve(0, max_t));
    #endif

    #ifndef RECURSION
    int t;
    for (int i = n - 1; i >= 0; --i)
    {
        for (int j = 0; j <= max_t; ++j)
        {
            t = ls[i];
            num[i][j] = num[i + 1][j];
            for (int k = 0; k < ms[i]; ++k)
            {
                t += ts[i][k];
                if (t > j)
                    break;

                num[i][j] = max(num[i][j], num[i + 1][j - t] + k + 1);
            }
        }
    }

    printf("%d\n", num[0][max_t]);
    #endif
}

正如您在递归版本中看到的那样,有一行max_num = max(max_num, solve(i + 1, tleft - t) + j + 1);。由于t增加一个整数而不总是= 1,因此会跳过某些情况。但是,在迭代版本中,会计算许多无用的状态。

我认为如果迭代解决方案更快,那么递归必须比迭代慢得多。我的主张是否正确?

2 个答案:

答案 0 :(得分:1)

性能优化是一个非常复杂的领域,你通常不能将其简化为简单的建议,例如&#34;迭代比递归更快#34;。

计数器示例非常快:例如,大多数最快的排序算法(如Quicksort)通常是递归实现的。

在您的情况下,经常进行一些廉价操作可能会比执行复杂检查以防止它们更快,例如,因为缓存未命中次数较少。判断一种解决方案是否优于另一种解决方案的唯一方法是使用分析器进行仔细分析。

看到这个优秀的答案(实际上它更像是一篇文章)涵盖分支预测Why is it faster to process a sorted array than an unsorted array?

答案 1 :(得分:0)

Theoratically iterative == recursive,授予您不使用编译器优化。 主要区别在于堆栈通过递归解决方案填充了函数调用。 然而,递归通常更容易转换为多线程应用程序。 此外,如果你有很多if语句,递归解决方案有助于使代码更抽象,你可以很容易地在执行过程中切换到另一种类型的递归(只是以不同方式调用函数或调用完全不同的函数)。 / p>