2013-04-21 174 views
0

我很好奇在使用遞歸函數時返回是如何工作的。例如,在下面的階乘函數中,在任何計算實際發生之前x都將達到1。帶遞歸函數返回

int factorial (int x){ 
    if (x==1){ 
     return 1;  
}else{ 
    return x * factorial(x - 1); 
    } 
} 

假設x = 3。繼邏輯,現在看來,這應該循環3次,並返回1:

  • 3 != 1
  • 所以別人:3 * factorial (2)
  • 什麼是factorial (2)
  • 那麼返回頂部:2 != 1
  • 如此:2 * factorial (1)
  • 什麼是factorial (1)
  • 返回頂部:1 == 1,
  • 所以:return 1

但是,當然它實際上會返回6.所以它是如何工作的?

+3

實驗!你就是這樣學習的。 – 2013-04-21 01:00:01

+1

你應該閱讀一個基本的遞歸教程。基本上,您有一個調用堆棧,直到您到達基本案例(在本例中爲'x == 1')爲止,然後將調用堆棧解析爲「向後」,直到它返回第一個函數調用。 – 2013-04-21 01:01:24

+0

[理解遞歸]的可能的重複(http://stackoverflow.com/questions/717725/understanding-recursion) – 2013-04-21 01:03:57

回答

1

每次你說「這個遞歸調用的價值是什麼?」時,你會放棄上一次迭代的x *。如果不這樣做:

factorial(3) 
3 * factorial(2) 
3 * (2 * factorial(1)) 
3 * (2 * 1) 
= 6 

遞歸調用是不是有新的論點再次喜歡goto到函數的頂部。 我們用新的參數再次調用該函數,但只有該調用具有新的參數值:調用方仍然具有其參數和變量的舊值。

除非我們正在談論尾部遞歸,我們不這樣做,而這只是一個優化。

1

這不是返回頂部,它調用factorial函數中的factorial函數。

實際上,在結束時,則返回1,但它返回它作爲結果在線路

return x * factorial(x - 1); 
先前呼叫的

factorial到,其中x爲2這又返回2 * 1到之前調用factorial的地方,其中x是3.所以這給出3 * 2,返回結果 - 6 - 函數的第一次調用。

0

遞歸函數調用與普通函數調用沒有區別。因此,一個呼叫的return與另一呼叫的return之間沒有關聯。

在該示例中,第一return語句是

return 3 * factorial(2) 

其通過調用factorial爲2的參數的返回值乘以3。

但是階乘的返回值(2)是

return 2 * factorial(1) 

其通過調用factorial用的1

參數但是階乘的返回值的返回值乘以2(1)是1。

所以return 2 * factorial(1)相同return 2 * 1,它是2。

所以return 3 * factorial(2)是叔他與return 3 * 2相同,即6.

0

第一步,x = 3。你的函數然後返回3 * factorial(2),這本身就返回2 * factorial(1)(因爲x仍然不等於1),最後,factorial(1)返回1

所以最後你得到3 * 2 * 1 = 6

0

棧幀是一個記錄,它在運行時用於存儲有關函數調用的信息,包括參數,局部變量,寄存器值和返回地址。對於每個連續的函數調用,我們都將堆棧幀壓入堆棧,並且當任何活動函數(位於堆棧頂部的函數)返回調用時,堆棧框架將從堆棧中彈出,並且其下面的函數將被激活。這裏是例子。

enter image description here

所以,最後的功能階乘(3)的返回值6