递归和非递归实现之间的速度比较

时间:2011-05-18 11:11:53

标签: performance caching recursion stack heap

我有一个复杂的算法,它使用非常深的递归。因为有一些特定数据的堆栈溢出,我试图在没有递归的情况下重写它(在堆上使用外部堆栈)。所以我对同一算法进行了两次修改。然后我进行了一些测试,我发现递归实现比另一个更快。

有人可以向我解释一下吗?这是我最后一个大学项目讨论这些结果的一部分(为什么一个实现比另一个实现快得多)。我认为这是因为堆栈和堆的缓存不同,但我不确定。

非常感谢!


修改

好的,有一个代码。该算法用C ++编写,解决了树同构问题。除了一种比较两个节点的方法外,两种实现都是相同的比较是递归定义的 - 如果一个节点中的一个节点小于另一节点的相应子节点,则一个节点小于另一个节点。

递归版

char compareTo( const IMisraNode * nodeA, const IMisraNode * nodeB ) const {
    // comparison of same number of children
    int min = std::min( nodeA->getDegree( ), nodeB->getDegree( ) );
    for ( int i = 0; i < min; ++i ) {
        char res = compareTo( nodeA->getChild( i ), nodeB->getChild( i ) );
        if ( res < 0 ) return -1;
        if ( res > 0 ) return 1;
    }
    if ( nodeA->getDegree( ) == nodeB->getDegree( ) ) return 0; // same number of children
    else if ( nodeA->getDegree( ) == min ) return -1;
    else return 1;
}

非递归实施

struct Comparison {
    const IMisraNode * nodeA;
    const IMisraNode * nodeB;
    int i;
    int min; // minimum of count of children

    Comparison( const IMisraNode * nodeA, const IMisraNode * nodeB ) :
    nodeA( nodeA ), nodeB( nodeB ),
    i( 0 ), min( std::min( nodeA->getDegree( ), nodeB->getDegree( ) ) ) { }
} ;

char compareTo( const IMisraNode * nodeA, const IMisraNode * nodeB ) const {
    Comparison * cmp = new Comparison( nodeA, nodeB );
    // stack on the heap
    std::stack<Comparison * > stack;
    stack.push( cmp );

    char result = 0; // result, the equality is assumed

    while ( !result && !stack.empty( ) ) { // while they are not same and there are nodes left
        cmp = stack.top( );

        // comparison of same children
        if ( cmp->i < cmp->min ) {
            // compare these children
            stack.push( new Comparison( cmp->nodeA->getChild( cmp->i ), cmp->nodeB->getChild( cmp->i ) ) );
            ++cmp->i; // next node
            continue; // continue in comparing on next level
        }
        if ( cmp->nodeA->getDegree( ) != cmp->nodeB->getDegree( ) ) { // count of children is not same
            if ( cmp->nodeA->getDegree( ) == cmp->min ) result = -1; // node A has lesser count of children
            else result = 1; 
        }
        delete cmp;
        stack.pop( );
    }

    while ( !stack.empty( ) ) { // clean stack
        delete stack.top( );
        stack.pop( );
    }

    return result;
}

2 个答案:

答案 0 :(得分:2)

您的非递归代码执行动态内存分配(显式使用new,并使用std :: stack隐式),而递归代码不执行。动态内存分配是一项非常昂贵的操作。

为了加快速度,尝试存储值,而不是指针:

stack <Comparison> astack;

然后代码如下:

astack.push( Comparison( cmp->nodeA->getChild( cmp->i ), cmp->nodeB->getChild( cmp->i ) ) );

Comparison cp = astack.top();

答案 1 :(得分:0)

这不能回答你的速度比较问题,而是建议增加递归解决方案的堆栈大小的方法。

您可以在VC ++下增加堆栈大小(默认值:1MB):在Visual Studio帮助中搜索“stacksize”。

你可以在gcc下做同样的事情。在这个问题上有一个SO discussion