函數的遞歸調用

一個函數在它的函數體內調用它自身稱爲遞歸調用,這種函數稱爲遞歸函數。執行遞歸函數將反覆調用其自身,每調用一次就進入新的一層。

【示例】用遞歸計算 n!。階乘 n! 的計算公式以下:

根據公式編程:html

  1. long factorial(int n){
  2. long result;
  3. if(n==0 || n==1){
  4. result = 1;
  5. }else{
  6. result = factorial(n-1) * n; // 遞歸調用
  7. }
  8. return result;
  9. }

這是一個典型的遞歸函數。調用factorial後即進入函數體,只有當 n==0 或 n==1 時函數纔會執行結束,不然就一直調用它自身。

因爲每次調用的實參爲 n-1,即把 n-1 的值賦給形參 n,因此每次遞歸實參的值都減 1,直到最後 n-1 的值爲 1 時再做遞歸調用,形參 n 的值也爲1,遞歸就終止了,會逐層退出。

例如求 5!,即調用factorial(5)。當進入factorial函數體後,因爲 n=5,不等於0或1,因此執行result = factorial(n-1) * n;,即result = factorial(5-1) * 5;,接下來也就是調用factorial(4)。這是第一次遞歸。

進行四次遞歸調用後,實參的值爲 1,也就是調用factorial(1)。這時遞歸就結束了,開始逐層返回。factorial(1) 的值爲 1,factorial(2) 的值爲 1*2=2,factorial(3) 的值爲 2*3=6,factorial(4) 的值爲 6*4=24,最後返回值 factorial(5) 爲 24*5=120。編程

注意:爲了防止遞歸調用無終止地進行,必須在函數內有終止遞歸調用的手段。經常使用的辦法是加條件判斷,知足某種條件後就再也不做遞歸調用,而後逐層返回。

遞歸調用不但難於理解,並且開銷很大,如非必要,不推薦使用遞歸。不少遞歸調用能夠用迭代(循環)來代替。

【示例】用迭代法求 n!。函數

  1. long factorial(int n){
  2. int i;
  3. long result=1;
  4. if(n==0 || n==1){
  5. return 1;
  6. }
  7. for(i=1; i<=n; i++){
  8. result *= i;
  9. }
  10. return result;
  11. }

關於函數調用的原理,請你們閱讀《C語言和內存》中的《棧的概念以及棧溢出》《一個函數在棧上究竟是怎樣的》《詳細分析一個函數進棧出棧的例子》幾節,屆時你將會明白遞歸調用的開銷爲何很大。spa

相關文章
相關標籤/搜索