成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

進階JavaScript之玩轉遞歸與數列

開發 前端
在程序中,所謂的遞歸,就是函數自己直接或間接調用自己。就遞歸而言,最重要的是跳出結構,因為只有跳出結構才可以有結果。

1、 什么是遞歸

在程序中,所謂的遞歸,就是函數自己直接或間接調用自己

1.1 直接調用自己

  1. function f() { 
  2.     console.log( 1 ); 
  3.     f(); 
  4.  

1.2 間接調用自己

  1. function f1(){ 
  2.     f2(); 
  3. function f2() { 
  4.     f1(); 
  5.  

就遞歸而言,最重要的是跳出結構,因為只有跳出結構才可以有結果。

1.3 所謂的遞歸就是化歸思想

遞歸的調用,寫遞歸函數,最終還是要轉換為自己這個函數

加入有一個函數f,如果他是遞歸函數的話,也就是說函數體內的問題還是轉化為 f 的形式。

遞歸思想就是將一個問題轉換為一個已解決的問題來實現

例子:1,2,3,4,...,100,累加的結果

  • 首先假定遞歸函數已經寫好,假設是foo,即foo(100) 就是求1到100的和
  • 尋找遞推關系,就是n與n-1,或n-2之間的關系:foo( n ) == n + foo( n -1 )
  1. var res = foo( 100 ); 
  2. var res = foo( 99 ) + 100;  
  • 將遞推結果轉換為遞歸體
  1. function foo ( n ) { 
  2.     return n + foo( n -1 ); 
  3.  
  1. 將求100轉換為求99
  2. 將求99轉換為求98
  3. ...
  4. 將求2轉換為求1
  5. 求1結果就是1
  6. 即:foo( 1 ) 是1
  • 將臨界條件加到遞歸體中
  1. function foo( n ) { 
  2.     return ( n ==1 ) return 1; 
  3.     return n + foo( n -1 ); 
  4.  

2、 遞歸求值舉例

2.1 等差數列1

數列:求 1, 3, 5, 7, 9, ... 第 n 項的結果與前 n 項和. 序號從 0 開始

求第 n 項的值

  • 首先假定遞歸函數已經寫好, 假設是 fn. 那么 第 n 項就是 fn( n )
  • 找遞推關系: fn( n ) == f( n - 1 ) + 2
  • 遞歸體
  1. function fn( n ) { 
  2.     return fn( n-1 ) + 2; 
  3.  
  • 找臨界條件

         求 n -> n-1

        求 n-1 -> n-2

        ...

        求 1 -> 0

        求 第 0 項, 就是 1

  • 加入臨界條件 
  1. function fn( n ) { 
  2.     if ( n == 0 ) return 1; 
  3.     return fn( n-1 ) + 2; 
  4.  

前N項的和

  • 假設已完成, sum( n ) 就是前 n 項和
  • 找遞推關系: 前 n 項和 等于 第 n 項 + 前 n-1 項的和
  • 得到遞歸體 
  1. function sum( n ) { 
  2.     return fn( n ) + sum( n - 1 ); 
  3. }   
  • 找臨界條件

          n == 1 結果為1

  • 得到遞歸函數 
  1. function sum( n ) { 
  2.     if ( n == 0 ) return 1; 
  3.     return fn( n ) + sum( n - 1 ); 
  4. }   

2.2 等差數列2

數列:2, 4, 6, 8, 10 第 n 項與 前 n 項和

第n項

  1. function fn( n ) { 
  2.    if ( n == 0 ) return 2;  
  3.    return fn( n-1 ) + 2;  
  4.  

前n項和 

  1. function sum( n ) {  
  2.    if ( n == 0 ) return 2;  
  3.    return sum( n - 1 ) + fn( n );  
  4.  

2.3 差分數列

數列: 1, 1, 2, 4, 7, 11, 16, … 求 第 n 項, 求前 n 項和.

求第 n 項,從0開始

  • 假設已經得到結果 fn, fn( 10 ) 就是第 10 項
  • 找遞推關系

          第 0 項和第 1 項,相差0 => fn( 0 ) + 0 = fn( 1 )

          第 1 項和第 2 項,相差1 => fn( 1 ) + 1 = fn( 2 )

          第 2 項和第 3 項,相差2 => fn( 1 ) + 2 = fn( 2 )

          ...

          第 n-1 項和第 n 項,相差n-1 => fn( n -1 ) + n -1 = fn( n )

  • 遞歸體也就清楚了, 臨界條件是 n == 0 => 1 
  1. function fn ( n ){ 
  2.     if( n == 0 ) return 1; 
  3.     return fn( n -1 ) + n - 1; 
  4.  

如果從 1 開始表示, 那么第 n 項為

  • 假設已經得到結果 fn, fn( 10 ) 就是第 10 項
  • 找遞推關系

         第 1 項和第 2 項,相差0 => fn( 1 ) + 0 = fn( 2 )

         第 2 項和第 3 項,相差1 => fn( 2 ) + 1 = fn( 3 )

         第 3 項和第 4 項,相差2 => fn( 3 ) + 2 = fn( 4 )

         ...

        第 n-1 項和第第 n 項,相差 n - 1 => fn( n -1 ) + n -2 = fn( n )

  • 臨界條件 n == 1 => 1

前n項和

  1. function sum( n ) { 
  2.     if ( n == 1 ) return 1; 
  3.     return sum( n - 1 ) + fn( n );  

 2.4 斐波那契數列

這是最常見,面試***問的知識之一,斐波那契數列為:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, …

求其第 n 項

遞推關系 fn(n) == fn( n- 1) + fn( n - 2),于是,遞歸函數為 

  1. function fib ( n ) { 
  2.     if( n ==0 || n == 1 ) return 1; 
  3.     return fib( n -1 ) + fib( n -2 ); 
  4.  

3、高級遞歸

3.1 階乘

計算階乘是遞歸程序設計的一個經典示例。階乘是一個運算,計算某個數的階乘就是用那個數去乘包括 1 在內的所有比它小的數。例如,factorial(5) 等價于 5*4*3*2*1,而 factorial(3) 等價于 3*2*1。

5! 就是 1 * 2 * 3 * 4 * 5. 0 的階乘是1, 階乘 從 1 開始。

求 n 的階乘

  1. function foo( n ){ 
  2.     if( n == 1 ) return 1; 
  3.     return foo( n -1 ) * n;  
  4. console.log(foo(5));    //120 

 

跟前面的1到100的求和的遞歸函數很相似,只是一個變種

3.2 求冪

求冪就是求 某一個數 幾次方

2*2 2 的 平方, 2 的 2 次方

求 n 的 m 次方

最終要得到一個函數 power( n, m )

n 的 m 次方就是 m 個 n 相乘 即 n 乘以 (m-1) 個 n 相乘

  1. function power( n, m ) { 
  2.     if( m == 1 ) return n; 
  3.     return power( n , m -1 ) * n; 
  4.  
  5. console.log(power(2,3)); //8 

 

4、遞歸深拷貝

如果要實現深拷貝,那么就需要考慮將對象的屬性,與屬性的屬性,....都拷貝過來

4.1 簡單實現

如果要實現:

  • 假設已經實現clone( o1,o2 ),將對象 o2 的成員拷貝一份交給 o1
  • 簡單的算法,將 o2 的屬性拷貝到 o1 中去
  1. function clone( o1,o2 ){ 
  2.     for( var k in o2 ){ 
  3.         o1[ k ] = o2[ k ];  
  4.     } 

 

  • 找遞推關系,或叫化歸為已解決的問題

          假設方法已經實現,問一下,如果o2[ k ] 是對象

          繼續使用這個方法

          因此需要考慮的是o2[ k ] 如果是引用類型,再使用一次clone()函數

          如果o2[ k ] 不是引用類型,那么就直接賦值

  1. function clone( o1, o2 ) { 
  2.         for ( var k in o2 ) { 
  3.             if ( typeof o2[ k ] == 'object' ) { 
  4.                 o1[ k ] = {}; 
  5.                 clone( o1[ k ] , o2[ k ] ); 
  6.             } else { 
  7.                 o1[ k ] = o2[ k ]; 
  8.             } 
  9.         } 
  10.  
  11. var person1 = { 
  12.        name'張三'
  13.        children: [ 
  14.             { name'張一' }, 
  15.             { name'張二' }, 
  16.             { name'王三' } 
  17.        ] 
  18. }; 
  19.  
  20. var person2 = {}; 
  21. clone( person2, person1 ); 

 

4.2 復雜實現 clone( o ) -> newObj

  1. function clone( o ) { 
  2.     var temp = {}; 
  3.     for( var k in o ) { 
  4.         if( typeof o[ k ] == 'object' ){ 
  5.              temp[ k ] = clone( o[ k ] ); 
  6.         } else { 
  7.              temp[ k ] = o[ k ]; 
  8.         } 
  9.     } 
  10.     return temp
  11.  
  12. var person1 = { 
  13.      name'張三'
  14.      children: [ 
  15.         { name'張一' }, 
  16.         { name'張二' }, 
  17.         { name'王三' } 
  18.     ] 
  19. }; 
  20.   
  21.  var person2 = clone(person1); 
  22. // 修改一個看另一個是否也修改 
  23. person2.name = '李四'
  24.   
  25. person2.children[ 0 ].name = '王小虎'
  26. person2.children[ 1 ].name = '張大虎'
  27. person2.children[ 2 ].name = '李長虎'

 

4.3 遞歸實現getElementsByClassName方法

有如下DIV結構:

  1. <div> 
  2.     <div>1 
  3.         <div class="c">2</div> 
  4.         <div>3</div> 
  5.     </div> 
  6.     <div class="c">4</div> 
  7.     <div>5 
  8.         <div>6</div> 
  9.         <div class="c">7</div> 
  10.     </div> 
  11.     <div>8</div> 
  12. </div> 

 

  1. 如果實現一個方法byClass( node, 'c', list ),表示在某個節點上查找符合 class 屬性為 c 的元素
  2. 在當前元素的子元素中查找,如果有符合要求的嗎,存儲早一個數組中
  3. 首先遍歷子節點,然后看子節點是否還有子節點,如果沒有直接判斷,如果有再遞歸
  1. function byClass( node, className, list ){ 
  2.     var nodes = node.childNodes; 
  3.     for( var i=0; i<ndoes.length; i++ ){ 
  4.          if( nodes[ i ].className == className ){ 
  5.              list.push( nodes[ i ] ); 
  6.          } 
  7.          if( nodes[ i ].childNodes.length > 0 ){ 
  8.              byClass( nodes[ i ], className, list ); 
  9.          } 
  10.     } 
  11.  
  12. var arr = []; 
  13. byClass( document.body, 'c', arr ); 
  14. console.log(arr); 

 

責任編輯:龐桂玉 來源: segmentfault
相關推薦

2014-04-16 10:54:45

Javascript遞歸調用

2020-03-09 17:18:47

JavaScript技術函數

2021-08-25 07:43:17

AndroidSurfaceViewTextureView

2025-05-07 10:10:00

SystemdLinux運維

2020-12-10 06:01:20

前端Compose方法

2017-08-08 09:15:41

前端JavaScript頁面渲染

2019-07-16 10:35:54

JavaScript進階字符串

2011-07-20 10:27:29

JavaScript

2016-09-06 21:23:25

JavaScriptnode異步

2022-11-08 10:19:15

2022-07-29 08:06:31

物聯網終端安全

2022-03-09 09:00:41

SwiftUI視圖生成器Swift

2009-06-30 16:46:45

Criteria進階查

2022-03-01 09:01:56

SwiftUI動畫進階Canvas

2010-10-27 13:55:01

memoization遞歸JavaScript

2021-11-29 08:50:57

Javascript存儲函數

2012-02-22 10:14:44

Java

2017-01-19 19:07:28

iOS進階性能優化

2021-12-09 22:36:30

Java 字節碼頁緩存

2014-04-04 11:14:18

JavaScriptStack遞歸
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 91婷婷韩国欧美一区二区 | 888久久久| 久久蜜桃资源一区二区老牛 | 不卡一区| 国产精品久久 | 日韩精品久久一区二区三区 | 成人国产一区二区三区精品麻豆 | 亚洲免费在线观看视频 | 成人h片在线观看 | av在线一区二区三区 | 久久久99精品免费观看 | 91影片| 亚洲精品美女视频 | 青青草精品视频 | 国精日本亚洲欧州国产中文久久 | 干干天天 | 欧美日韩高清一区 | 久久国产精品久久久久 | 操久久| 国产aa| 欧美日日 | 日韩激情一区 | 黄色免费av | 中文字幕精品视频 | 91精品国产综合久久国产大片 | 一级全黄少妇性色生活免费看 | 91久久精品日日躁夜夜躁欧美 | aaaaaa大片免费看最大的 | 国产精品久久久久婷婷二区次 | 91久久国产综合久久 | 91精品国产色综合久久 | 日韩久久综合网 | 午夜伦理影院 | www.狠狠操| 日韩欧美一区二区三区在线播放 | 国产精品一区一区 | av黄色在线 | 一级黄色片网站 | 久久精品91| 欧美黑人激情 | 在线视频第一页 |