JavaScript中的遞歸

JavaScript遞歸函數

1.遞歸定義優化

遞歸簡而言之就是一個函數調用自己或者兩個函數相互調用,咱們只討論第一種狀況,須要注意的是, 遞歸是一個比較難以理解的概念,看不懂, 不理解, 太正常了,這須要時間來, 慢慢搞懂它spa

注意:接下來的例子都只是例子而已, 實際不會這麼寫代碼,遞歸有適用的場景, 但不會用來求階乘這樣的事情,只是爲了簡化描述才用了這個例子指針

 

(1)遞歸求階乘code

 1 var fac = function(n) {
 2     // 若是 n 是 0 則返回 1
 3     // 這是遞歸終止的條件, 必需要有, 不然無限遞歸了
 4     if(n == 0) {
 5         return 1
 6     } else {
 7         // 若是 n 不爲 0, 返回 n * fac(n-1)
 8         // 這時候 n 是已知的, fac(n-1) 須要計算
 9         // 因而代碼進入下一重世界開始計算
10         return n * fac(n-1)
11     }
12 }
13 
14 console.log('遞歸階乘', fac(5))  // 120

 

(2)遞歸求斐波那契數blog

 1 var fib = function(n) {
 2     // 若是 n 是 1 或者 2 則返回 1 做爲結果
 3     // 這是遞歸終止的條件, 必需要有, 不然無限遞歸了
 4     if(n == 1 || n == 2) {
 5         return 1
 6     } else {
 7         // 若是 n 不爲 1 和 2, 返回 fib(n-2) + fib(n-1)
 8         // 這時候 fib(n-2) fib(n-1) 須要計算
 9         // 因而代碼進入下一重世界開始計算
10         return fib(n-2) + fib(n-1)
11     }
12 }
13 
14 console.log('遞歸 fib: ', fib(6))  // 8

 

 

2.經典遞歸遞歸

一共10級樓梯,每次能夠走一步或兩步,求一共多少種走法,思路:ip

要想走到N(N=10)級,能夠分爲2種狀況。it

  1. 從n-2級邁兩步
  2. 從n-1級邁一步

那麼對於n-2和n-1的狀況也是各自分爲兩種,以此類推。io

那麼走法的和就是n-2的走法和n-1的走法之和。

那麼遞歸到最基本的(當前人在第0階臺階)

第0階臺階:0

第1階臺階:1

第2階臺階:2(1+1或者2)

獲得公式,也就是斐波那契數列。

 1 var fib = function (n){
 2     if(n == 1){ 3 return 1; 4  } 5 else if(n==2){ 6 return 2; 7  } 8 else if(n>2){ 9 return fib(n-1) + fib(n-2); 10  } 11 } 12 13 console.log(fib(10));

 

 

3.JavaScript遞歸中的注意問題

當使用函數表達式來遞歸時可能會致使一些問題:

 1 // 函數表達式與遞歸:
 2 var func = function (num) {
 3     if (num<=1){
 4         return 1;
 5     }      
 6     else{
 7         return num * func(num-1);
 8     }
 9 };
10 var anotherFunc = func;
11 func = null;
12 console.log(anotherFunc(4));  // 報錯!

出錯緣由:func變量執行上述操做後爲空,結果指向原始函數的引用就只剩下一個,可是在接下來的調用anotherFunc中必須執行func,而func已經不是函數了,因此就致使錯誤出現,在這種狀況下使用aruguments.callee能夠解決這個問題

aruguments.callee:是一個指向函數的指針,所以能夠用它來實現對函數的遞歸調用

 1 // 函數表達式與遞歸:
 2 var func = function (num) {
 3     if (num<=1){
 4         return 1;
 5     }      
 6     else{
 7         return num * arguments.callee(num-1);
 8     }
 9 };
10 var anotherFunc = func;
11 func = null;
12 console.log(anotherFunc(4));  // 24

另外arguments.callee能夠實現匿名函數的遞歸調用:

 1 // 匿名函數的遞歸調用
 2 (
 3     function (count) {
 4         if(count<=3){
 5             console.log(count);
 6             arguments.callee(++count);
 7         }
 8     }
 9 )(0);
10 
11 // 輸出結果: 0 1 2 3

 

 

4.尾遞歸

尾遞歸:是一種在函數的最後執行遞歸調用語句的特殊形式的遞歸

尾遞歸示例:

1 var factorial = function(i, a) {
2     a = a || 1;  // 1是默認值
3     if (i < 2) {
4         return a;
5     }
6         // 返回自身調用的結果 -》 尾遞歸 -》JavaScript沒有對這種遞歸作優化 
7     return factorial(i - 1, a * i);
8 };
9 document.writeln(factorial(4));  // 24
相關文章
相關標籤/搜索