簡體   English   中英

停止回溯

[英]Stopping Backtracking

在沒有退出程序的情況下找到第一個解決方案之后,C / C ++中是否有任何方法可以停止回溯算法。

我希望我的函數立即退出函數,而不是逐個退出每個級別的reurrsion表示返回。

在不確切知道你需要什么的情況下,我會考慮實現你自己的堆棧,並完全避免遞歸。 這樣退出回溯樹(單個“返回”)變得微不足道,並且還可以通過再次調用該函數來恢復搜索以找到下一個解決方案,假設保留了用戶定義堆棧的狀態(在靜態變量中)。 當然,將簡單的遞歸程序轉換為循環會有一些編程開銷,但這很簡單。

一個快速而骯臟的方法是拋出異常並在基礎級別捕獲它(現在很多人會尖叫到只使用異常錯誤,我認為,創建一個解決方案是一個例外事件,因為沒有找到一個是規范)

如果你有一個標志,當你完成后設置,然后在你的功能中檢查,你可以解決這個問題。 例如

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

它實際上取決於你的實現,但你可以設置一些特殊的參數並將其用作“我們是否得到解決方案?如果是,那么中止當前例程並僅獲得輸出的解決方案”的標志。

為什么要讓函數立即退出? 不回溯堆棧是危險的,因為你可能有需要銷毀的對象。 拋出異常可能是由於你的技巧,它將清理堆棧。 提供有關您嘗試執行的操作的更多信息,我們可能會提供其他方法。

您可以在C和C ++中使用setjmp()/ longjmp(),這是一種原始但有效的方法,可以繞過傳遞標志的必要性。

如果你的回溯算法實際上已經足夠深入地重復這一點,那么你就不應該使用遞歸,因為你將面臨摧毀堆棧的危險。 您應該考慮使用您自己的堆分配堆棧將算法重寫為迭代方法,而不是提交涉及longjmp的某些暴行,該堆棧存儲表示狀態的POD對象。 當您找到解決方案時,可以通過一個有效的步驟銷毀狀態容器,並返回答案。

請參閱從遞歸到迭代的方法

首先,請注意您不能為任何遞歸函數執行此操作。 請考慮以下代碼:

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;
        }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM