停止回溯

时间:2010-04-25 14:22:43

标签: c++ c algorithm backtracking

在没有退出程序的情况下找到第一个解决方案后,C / C ++中是否有任何方法可以停止回溯算法。

我希望我的函数立即退出函数,而不是逐个退出每个级别的reurrsion表示返回。

8 个答案:

答案 0 :(得分:3)

如果不确切知道你需要什么,我会考虑实现你自己的堆栈,并完全避免递归。这样退出回溯树(单个“返回”)变得微不足道,并且还可以通过再次调用该函数来恢复搜索以找到下一个解决方案,假设保留了用户定义堆栈的状态(在静态变量中)。当然,将一个简单的递归程序转换为循环会有一些编程开销,但它非常简单。

答案 1 :(得分:2)

快速而肮脏的方法是抛出异常并在基础级别捕获它(现在很多人会尖叫到只使用异常错误,我认为,创建解决方案是一个特殊的事件,因为没有找到一个是常态)

答案 2 :(得分:2)

如果你有一个标志,当你完成后设置,然后在你的功能中检查,你可以解决这个问题。 e.g。

void foo(..)
{
   if (g_done) return;
...
}

答案 3 :(得分:1)

它实际上取决于你的实现,但你可以设置一些特殊的参数并将其用作“我们是否得到解决方案?如果是,那么中止当前例程并仅获得输出的解决方案”的标志。 / p>

答案 4 :(得分:1)

为什么要让函数立即退出?不回溯堆栈是危险的,因为你可能有需要销毁的对象。抛出异常可能是由于你的技巧,它将清理堆栈。提供有关您尝试做什么的更多信息,我们可能会提供其他方法。

答案 5 :(得分:0)

您可以在C和C ++中使用setjmp()/ longjmp(),这是一种原始但有效的方法,可以绕过将标志一直传回的需要。

答案 6 :(得分:0)

如果您的回溯算法实际上已经足够深入地重复这一点,那么您就不应该使用递归,因为您将面临摧毁堆栈的危险。您应该考虑使用您自己的堆分配堆栈将算法重写为迭代方法,而不是提交涉及longjmp的某些暴行,该堆栈存储表示状态的POD对象。当您找到解决方案时,可以在一个有效的步骤中销毁状态容器,并且可以返回答案。

请参阅Way to go from recursion to iteration

答案 7 :(得分:0)

首先,请注意您不能为任何递归函数执行此操作。 请考虑以下代码:

int SumNum(int nMax)
{
    if (0 == nMax)
        return 0;
    else
        return nMax + SumNum(nMax-1);
}

在回溯过程中计算实际值。

但是,您可以通过以下方式重写代码:

int SumNum(int nMax, int nSum)
{
    if (0 == nMax)
        return nSum;
    else
        return SumNum(nMax-1, nSum+nMax);
}

现在,您可以执行以下操作:

    int SumNum(int nMax, int nSum)
    {
        if (0 == nMax)
            throw nSum;
        else
            return SumNum(nMax-1, nSum+nMax);
    }


f()
{
        int nSum;

        try
        {
            SumNum(100, 0);
        }
        catch (int _nSum)
        {
            nSum= _nSum;
        }
}