[英]Understanding how a loop of recursive calls work
我真的對恢復性很陌生,偶然發現了一個練習,在這個練習中,我們有一個循環進行多次遞歸調用,但我不明白它是如何工作的。
看下面的例子:
int calculateSomething (int n) {
if (n > 100)
for (int i = 0; i < 10; i++)
calculateSomething(n+1);
}
假設我第一次撥打了calculateSomething(200),我將要接多少個電話? 乍一看,我會說100 * 10,所以1000個電話?
每個呼叫是否都將“ i”提高到10? 還是調用每個“ i”值?
很抱歉提出這樣的問題,但我確實阻止了XD
提前致謝 !
首先,您的示例代碼將無限循環使用,因為在您的所有遞歸調用中if( n>100 )
都會被評估為TRUE,因為您的“ n”值始終會增加。 calculateSomething(n+1)
如果您調用calculateSomething(200)
,則第一個遞歸調用將在for循環內,且i=0
, CalclulateSomething(201)
然后忘了for循環的下一個迭代,直到遞歸調用結束為止,並且正如我之前解釋的那樣,它將永遠不會發生。
calculateSomething(200)
-> i=0 calculateSomething(201)
-> i=0 calculateSomething(202)
-> i=0 calculateSomething(203)
-> ...infinite...
以下面的代碼為例:(修復了無限循環,並減小了值進行說明)
int calculateSomething (int n) {
if (n < 3)
for (int i = 0; i < 3; i++)
calculateSomething(n+1);
}
遞歸調用將是:
calculateSomething(0)
-> i=0 calculateSomething(1)
-> i=0 calculateSomething(2)
-> i=0 calculateSomething(3)
-> end. if (n < 3) = FALSE
-> i=1 calculateSomething(3)
-> end. if (n < 3) = FALSE
-> i=2 calculateSomething(3)
-> end. if (n < 3) = FALSE
-> i=1 calculateSomething(2)
-> i=0 calculateSomething(3)
-> end. if (n < 3) = FALSE
-> i=1 calculateSomething(3)
-> end. if (n < 3) = FALSE
-> i=2 calculateSomething(3)
-> end. if (n < 3) = FALSE
-> i=2 calculateSomething(2)
-> i=0 calculateSomething(3)
-> end. if (n < 3) = FALSE
-> i=1 calculateSomething(3)
-> end. if (n < 3) = FALSE
-> i=2 calculateSomething(3)
-> end. if (n < 3) = FALSE
-> i=1 calculateSomething(1)
-> i=0 calculateSomething(2)
-> i=0 calculateSomething(3)
-> end. if (n < 3) = FALSE
-> i=1 calculateSomething(3)
-> end. if (n < 3) = FALSE
-> i=2 calculateSomething(3)
-> end. if (n < 3) = FALSE
-> i=1 calculateSomething(2)
-> i=0 calculateSomething(3)
-> end. if (n < 3) = FALSE
-> i=1 calculateSomething(3)
-> end. if (n < 3) = FALSE
-> i=2 calculateSomething(3)
-> end. if (n < 3) = FALSE
-> i=2 calculateSomething(2)
-> i=0 calculateSomething(3)
-> end. if (n < 3) = FALSE
-> i=1 calculateSomething(3)
-> end. if (n < 3) = FALSE
-> i=2 calculateSomething(3)
-> end. if (n < 3) = FALSE
-> i=2 calculateSomething(1)
-> i=0 calculateSomething(2)
-> i=0 calculateSomething(3)
-> end. if (n < 3) = FALSE
-> i=1 calculateSomething(3)
-> end. if (n < 3) = FALSE
-> i=2 calculateSomething(3)
-> end. if (n < 3) = FALSE
-> i=1 calculateSomething(2)
-> i=0 calculateSomething(3)
-> end. if (n < 3) = FALSE
-> i=1 calculateSomething(3)
-> end. if (n < 3) = FALSE
-> i=2 calculateSomething(3)
-> end. if (n < 3) = FALSE
-> i=2 calculateSomething(2)
-> i=0 calculateSomething(3)
-> end. if (n < 3) = FALSE
-> i=1 calculateSomething(3)
-> end. if (n < 3) = FALSE
-> i=2 calculateSomething(3)
-> end. if (n < 3) = FALSE
如果要計算函數被調用的次數,可以簡單地添加一個conunter並為每個調用增加它,例如:
int counter = 0; // declaring it on a global scope
int calculateSomething (int n) {
counter++;
if (n < 3)
for (int i = 0; i < 3; i++)
calculateSomething(n+1);
}
即使返回類型為int,您所給的程序也沒有return語句。 而且,由於沒有結束條件,它將無限進行。
這將是執行周期
通話1:n = 200,i = 0計算方法(201次)
通話2:n = 201,i = 0calculateSomething(202)
通話3:n = 202,i = 0calculateSomething(203)...。
每個呼叫是否都將“ i”提高到10? 還是調用每個“ i”值?
調用i的每個值。 遞歸適用於堆棧(后進先出)。 在簡單的程序中,我從main調用Method1並從Method1調用Method2,看起來像這樣的堆棧
方法2
方法1
主要
基本上,最后一個調用將在頂部,一旦完成,它將轉到下一個。
由於您是新手,因此從一個簡單的示例(例如階乘)開始
public static int factorial(int n) {
if (n == 0) {
return 1;
} else {
System.out.println(n + " "+ (n-1));
return n * factorial(n - 1);
}
}
如果調用factorial(3),則堆棧看起來像
1(因為階乘(1-1),即階乘(0)為0)
1 *階乘(1-1)
2 *階乘(2-1)
3 *階乘(3-1)
factorial(3)->實際方法調用
現在,每次調用返回此處,它將用實際值替換其下面的一個因子(n-1),即
階乘(1-1)將替換為1
階乘(2-1)將替換為1 * 1
階乘(3-1)將替換為2 *(1 * 1)
factorial(3)變為3 *(2 *(1 * 1))
希望這可以幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.