所以我在測驗遞回函式,也就是說,函式是否會在第一次遞回時讓遞回完成然后繼續,或者它會簡單地初始化遞回并繼續,也就是說遞回呼叫會同時列印數字還是首先它會列印num到 1 然后它會列印num到 100 ;無論如何,當我給出num23 時,我的編譯器只是無限輸出 32 ;
void print(int num){
if(num == 1 || num == 100){
return;
}
std::cout << num ;
print(num-1);
std::cout << std::endl;
print(num 1);
return;
}
uj5u.com熱心網友回復:
那是因為當你到達 時num == 2,發生的是你呼叫print(1)并停止遞回,所以你去換行,然后呼叫print(3)列印 32 然后停止遞回,但它會print(3)在某個時候再次呼叫。
在遞回情況下,任何遞回演算法都必須更接近遞回的結尾,這不是發生的情況,因為num作為引數,您最終會呼叫print(num-1),print(num 1)因此您會從結尾更遠地回傳,因此遞回永遠不會結束。
uj5u.com熱心網友回復:
你在這里基本上做的是用 print() 呼叫淹沒堆疊,這是你對列印函式 print(num-1) 的第一次呼叫將被遞回呼叫,直到滿足一個停止條件。有時會滿足停止條件,但是由于您正在執行 1 和 -1,即在同一背景關系中呼叫該函式兩次而沒有額外檢查,它將創建一個無限遞回回圈的乒乓球,從而導致堆疊溢位
您所看到的“2”和“3”是函式呼叫在無限遞回乒乓球之前的最后一次列印
注意,任何不介于 1 和 100 之間的輸入都會使您的函式被無限呼叫
uj5u.com熱心網友回復:
為了使遞回發揮作用,就像數學歸納法一樣,應該有一個明確的進展方向。通常這意味著num應該在遞回的每一步中增加或減少,但不能同時減少。這不是您的函式的情況,它在增加和減少之間交替。
讓我們分析一下呼叫時會發生什么print(2)。這將同時呼叫print(1)和print(3)。顯然,print(1)立即退出但print(3)會繼續遞回。您希望3分支繼續到 4、5 等,但遞回將(想要)再次分成兩個方向:print(2)和print(4),而不是僅僅執行print(4)。
print(2)就像之前開始的那樣,有一種似曾相識的感覺。它會再次呼叫print(1)and print(3)。
最終,您將無限列印 2 和 3,或者您的程式可能由于堆疊溢位而崩潰。確切的行為(崩潰或無限運行)取決于編譯器是否足夠聰明,可以確定這是無限遞回。
我再重復一遍,要使遞回函式作業,它的后續呼叫必須在所有呼叫中遵循相同的方向 - 嚴格增加或減少。
如果有多個引數,則應該在所有呼叫中都遵循一些全序關系。因此,如果recursive(x1,y1,z1)呼叫recursive(x2,y2,z2),則(x1,y1,z1) < (x2, y2, z2)在此總命令下。
您滿足的另一個要求是在進展路徑上具有終止條件。如果您了解數學歸納法,請嘗試使用歸納法來證明您的演算法。
因此,在您的情況下,您可以通過同時遞回兩個引數來解決此問題:
- 一個引數將嚴格增加。
- 另一個引數將嚴格減少。
在運行代碼之前,請嘗試類似于揮手感應的解釋。步驟:每個引數是否朝著一個方向前進?Base:是否保證達到停止條件?正式的證明更復雜,但揮手解釋通常足以說服自己正確 - 或發現缺陷。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/425974.html
上一篇:對新關鍵字進行Gtest
