關於JavaScript遞歸經典案例題詳析

什麼是遞歸,它是如何工作的?

我們先來看一下遞歸(recursion)的定義:

遞歸是一種解決問題的有效方法,在遞歸過程中,函數將自身作為子例程調用。

簡單說程序調用自身的編程技巧叫遞歸。遞歸的思想是把一個大型復雜問題層層轉化為一個與原問題規模更小的問題,問題被拆解成子問題後,遞歸調用繼續進行,直到子問題無需進一步遞歸就可以解決的地步為止。

使用遞歸需要避免出現死循環,為瞭確保遞歸正確工作,遞歸程序應該包含2個屬性:

  1. 基本情況(bottom cases),基本情況用於保證程序調用及時返回,不在繼續遞歸,保證瞭程序可終止。
  2. 遞推關系(recurrentce relation),可將所有其他情況拆分到基本案例。

函數中自己調用自己就是遞歸,切記要有終止條件,不然進入死循環     

一、求和

(1)數字求和

    function sum(n){
      if(n===1){
        return n=1
      }
      return n+sum(n-1)
    }
    console.log(sum(5));

 執行順序

5+sum(n-1)
5+4+sum(n-1)
5+4+3+sum(n-1)
5+4+3+2sum(n-1)
5+4+3+2+1

(2)數組求和

        function sum(arr) {
        var len = arr.length
        if (len == 0) {
          return 0
        } else if (len == 1) {
          return arr[0]
        } else {
          return arr[0] + sum(arr.slice(1))
        }
      }
      let arr = [ 1, 2, 3, 4, 5 ]  
      console.log(sum(arr))

執行順序

1+sum(2,3,4,5)
1+2+sum(3,4,5)
1+2+3(4,5)
1+2+3+4+sum(5)
1+2+3+4+5
1+2+3+9
1+2+12
1+14
15

二、數據轉樹

        let data = [{
                id: "01",
                pid: "",
                "name": "老王"
            },
            {
                id: "02",
                pid: "01",
                "name": "小張"
            }
        ]
  function fn(data, rootId = '') {
            const children = []      //定義一個空數組
            data.forEach(item => {
                if (item.pid === rootId) {    //如果每一項的pid=rootId就添加到數組裡
                    children.push(item)
                    item.children = fn(data, item.id)
                }
            });
            return children
        }

使用遞歸轉樹 要知道根的pid是什麼值才能進行下一步操作,作為起點。

執行順序

三、漢諾塔

規則 下面三個柱子分別設為 a 、b、 c、 目標把a中的所有盤子分別從大到小依次放到c柱子中,每次隻能移動一個盤子

實現思路:

  1. 將n-1個盤子從a挪到b
  2. 將n盤子從a挪到c
  3. 將n-1個盤子從b挪到c
        function fn(num, start, middle, end) {   
            if(num>0){
                fn(num-1,start,end,middle)
                console.log(start+'====>'+end); 
                fn(num-1,middle,start,end)
            }
           }
              fn(2,'a','b','c')

把  num作為盤子的數量  start 作為a盤子  middle作為b盤子   end作為c盤子  

例如 2個盤子的執行順序

1.第一行 把2帶進去 num>0  執行第一個函數fn(2-1,start,end,middle) 又去執行瞭fn(1-1,start,end,middle) 發現num不大於0不僅如此if條件,回過來看 fn(2-1,start,end,middle) ,輸出 console.log(a===>b) 

2.第二行console.log(start+’====>’+end);   直接輸出 a===>c

3.第三行 fn(2-1,middle,start,end)  執行 console.log(b===>c)  下次再去執行  fn(1-1,middle,start,end) 進入不瞭循環執行完畢

執行順序有點抽象,實在不理解就按照最簡單的思路去做 fn(num, start, middle, end) ,平常我們玩遊戲怎麼玩就去怎麼做,初始圖

fn(num-1,start,middle,end)  把 第二個的參數位置作為要移動的盤子 把第四個的參數位置作為移動目標    每次看圖把這個公式帶進去 

第一步   fn(num-1,start,end,middle)   例如兩個盤子 肯定是先把a-1放到b上  

第二步 把盤子a放c上直接輸出 console.log(‘a===>c’)

第三步 把盤子b放c上  fn(num-1,middle,start,end,) 

四、斐波那契數列

斐波那契數列(Fibonacci sequence),又稱黃金分割數列,因數學傢萊昂納多·斐波那契(Leonardoda Fibonacci)以兔子繁殖為例子而引入,故又稱為“兔子數列”,指的是這樣一個數列:0、1、1、2、3、5、8、13、21、34、

        function Fibonacci(n) {
            return  n <= 1?1:Fibonacci(n - 1) + Fibonacci(n - 2)
        }

除瞭前兩個 每次都是前一個數和前兩個數的和相加等於第三個數 

例如數字5舉例  前一項是3  前兩項是2    3+2=5   

總結

到此這篇關於JavaScript遞歸經典案例題詳析的文章就介紹到這瞭,更多相關JavaScript遞歸案例內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: