[英]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.