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

提升JavaScript遞歸效率:Memoization技術(shù)詳解

開發(fā) 前端
遞歸是拖慢腳本運(yùn)行速度的大敵之一,太多的遞歸會(huì)讓瀏覽器變得越來(lái)越慢直到死掉或者莫名其妙的突然自動(dòng)退出。這里我們可以通過memoization技術(shù)來(lái)替代函數(shù)中太多的遞歸調(diào)用,提升JavaScript效率。

遞歸是拖慢腳本運(yùn)行速度的大敵之一。太多的遞歸會(huì)讓瀏覽器變得越來(lái)越慢直到死掉或者莫名其妙的突然自動(dòng)退出,所以我們一定要解決在JavaScript中出現(xiàn)的這一系列性能問題。

我們可以通過memoization技術(shù)來(lái)替代函數(shù)中太多的遞歸調(diào)用。memoization是一種可以緩存之前運(yùn)算結(jié)果的技術(shù),這樣我們就不需要重新計(jì)算那些已經(jīng)計(jì)算過的結(jié)果。

對(duì)于通過遞歸來(lái)進(jìn)行計(jì)算的函數(shù),memoization簡(jiǎn)直是太有用了。我現(xiàn)在使用的memoizer是由Crockford寫的,主要應(yīng)用在那些返回整數(shù)的遞歸運(yùn)算中。當(dāng)然并不是所有的遞歸函數(shù)都返回整數(shù),所以我們需要一個(gè)更加通用的memoizer()函數(shù)來(lái)處理更多類型的遞歸函數(shù)。

  1. function memoizer(fundamental, cache) {   
  2.   cachecache = cache || {};   
  3.   var shell = function(arg) {   
  4.       if (! (arg in cache)) {   
  5.           cache[arg] = fundamental(shell, arg);   
  6.       }   
  7.       return cache[arg];   
  8.   };   
  9.   return shell;   

這個(gè)版本的函數(shù)和Crockford寫的版本有一點(diǎn)點(diǎn)不同。首先,參數(shù)的順序被顛倒了,原有函數(shù)被設(shè)置為***個(gè)參數(shù),第二個(gè)參數(shù)是緩存對(duì)象,為可選參數(shù),因?yàn)椴⒉皇撬械倪f歸函數(shù)都包含初始信息。在函數(shù)內(nèi)部,我將緩存對(duì)象的類型從數(shù)組轉(zhuǎn)換為對(duì)象,這樣這個(gè)版本就可以適應(yīng)那些不是返回整數(shù)的遞歸函數(shù)。在shell函數(shù)里,我使用了in操作符來(lái)判斷參數(shù)是否已經(jīng)包含在緩存里。這種寫法比測(cè)試類型不是undefined更加安全,因?yàn)閡ndefined是一個(gè)有效的返回值。我們還是用之前提到的斐波納契數(shù)列來(lái)做說(shuō)明:

  1. var fibonacci = memoizer(function(recur, n) {   
  2.   return recur(n - 1) + recur(n - 2);   
  3. }, { "0": 0, "1": 1} ); 

同樣的,執(zhí)行fibonacci(40)這個(gè)函數(shù),只會(huì)對(duì)原有的函數(shù)調(diào)用40次,而不是夸張的331,160,280次。memoization對(duì)于那些有著嚴(yán)格定義的結(jié)果集的遞歸算法來(lái)說(shuō),簡(jiǎn)直是棒極了。然而,確實(shí)還有很多遞歸算法不適合使用memoization方法來(lái)進(jìn)行優(yōu)化。

有的觀點(diǎn)認(rèn)為,任何使用遞歸的情況,如果有需要,都可以使用迭代來(lái)代替。實(shí)際上,遞歸和迭代經(jīng)常會(huì)被作為互相彌補(bǔ)的方法,尤其是在另外一種 出問題的情況下。將遞歸算法轉(zhuǎn)換為迭代算法的技術(shù),也是和開發(fā)語(yǔ)言無(wú)關(guān)的。這對(duì)JavaScript來(lái)說(shuō)是很重要的,因?yàn)楹芏鄸|西在執(zhí)行環(huán)境中是受到限制的。讓我們回顧一個(gè)典型的遞歸算法,比如說(shuō)歸并排序,在JavaScript中實(shí)現(xiàn)這個(gè)算法需要下面的代碼:

  1. function merge(left, right) {   
  2.   var result = [];   
  3.   while (left.length > 0 && right.length > 0) {   
  4.       if (left[0] < right[0]) {   
  5.           result.push(left.shift());   
  6.       } else {   
  7.           result.push(right.shift());   
  8.       }   
  9.   }   
  10.   return result.concat(left).concat(right);   
  11. }  
  12.  
  13. //采用遞歸實(shí)現(xiàn)的歸并排序算法   
  14. function mergeSort(items) {   
  15.   if (items.length == 1) {   
  16.       return items;   
  17.   }   
  18.   var middle = Math.floor(items.length / 2),   
  19.   left = items.slice(0, middle),   
  20.   right = items.slice(middle);   
  21.   return merge(mergeSort(left), mergeSort(right));   

調(diào)用mergeSort()函數(shù)處理一個(gè)數(shù)組,就可以返回經(jīng)過排序的數(shù)組。注意每次調(diào)用mergeSort()函數(shù),都會(huì)有兩次遞歸調(diào)用。這個(gè)算法不可以使用memoization來(lái)進(jìn)行優(yōu)化,因?yàn)槊總€(gè)結(jié)果都只計(jì)算并使用一次,就算緩沖了結(jié)果也沒有什么用。如果你使用mergeSort()函數(shù)來(lái)處理一個(gè)包含100個(gè)元素的數(shù)組,總共會(huì)有199次調(diào)用。1000個(gè)元素的數(shù)組將會(huì)執(zhí)行1999次調(diào)用。在這種情況下,我們的解決方案是將遞歸算法轉(zhuǎn)換為迭代算法,也就是說(shuō)要引入一些循環(huán):

  1. // 采用迭代實(shí)現(xiàn)的歸并排序算法   
  2. function mergeSort(items) {   
  3.   if (items.length == 1) {   
  4.       return items;   
  5.   }   
  6.   var work = [];   
  7.   for (var i = 0,   
  8.   len = items.length; i < len; i++) {   
  9.       work.push([items[i]]);   
  10.   }   
  11.   work.push([]); //in case of odd number of items   
  12.   for (var lim = len; lim > 1; lim = (lim + 1) / 2) {   
  13.       for (var j = 0,   
  14.       k = 0; k < lim; j++, k += 2) {   
  15.           work[j] = merge(work[k], work[k + 1]);   
  16.       }   
  17.       work[j] = []; //in case of odd number of items   
  18.   }   
  19.   return work[0];   

這個(gè)歸并排序算法實(shí)現(xiàn)使用了一系列循環(huán)來(lái)代替遞歸進(jìn)行排序。由于歸并排序首先要將數(shù)組拆分成若干只有一個(gè)元素的數(shù)組,這個(gè)方法更加明確的執(zhí)行了這個(gè)操作,而不是通過遞歸函數(shù)隱晦的完成。work數(shù)組被初始化為包含一堆只有一個(gè)元素?cái)?shù)組的數(shù)組。

在循環(huán)中每次會(huì)合并兩個(gè)數(shù)組,并將合并后的結(jié)果放回work數(shù)組中。當(dāng)函數(shù)執(zhí)行完成后,排序的結(jié)果會(huì)通過work數(shù)組中的***個(gè)元素返回。在這個(gè)歸并排序的實(shí)現(xiàn)中,沒有使用任何遞歸,同樣也實(shí)現(xiàn)了這個(gè)算法。

【編輯推薦】

  1. JavaScript中的函數(shù)式編程實(shí)踐
  2. JavaScript函數(shù)的定義及形式參數(shù)
  3. 揭開Javascript閉包的真實(shí)面目 

 

責(zé)任編輯:王曉東 來(lái)源: JavaEye博客
相關(guān)推薦

2009-03-11 17:31:46

2015-10-08 17:15:20

RFID技術(shù)物聯(lián)網(wǎng)

2025-01-07 10:48:08

2024-10-15 10:11:04

2025-03-04 13:00:00

JavaScrip代碼語(yǔ)言

2020-08-11 08:11:40

JavaScript開發(fā)技術(shù)

2025-03-03 00:15:00

JavaScript開發(fā)效率

2020-07-25 19:38:54

JavaScriptJavaScript庫(kù)Web

2012-04-19 10:23:03

虛擬化微虛擬化

2012-06-26 09:55:38

2020-03-23 09:31:51

JavaScript函數(shù)技術(shù)

2022-01-19 16:13:20

戴爾

2020-06-16 10:00:00

航空

2017-12-21 19:53:25

潤(rùn)乾蔣步星

2020-10-19 15:39:34

人工智能

2020-07-17 10:40:35

人工智能

2013-04-02 10:10:06

JavaScriptJS

2011-07-08 10:22:12

智能布線

2024-10-09 12:18:38

2009-11-27 15:24:48

PHP遞歸效率
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 欧美视频二区 | 欧美国产精品 | 91精品91久久久 | 日韩高清国产一区在线 | 成人性生交大片免费看中文带字幕 | 性高湖久久久久久久久aaaaa | 欧美激情欧美激情在线五月 | 欧美成人激情 | 日本一道本视频 | 99精品免费 | 久久99精品久久久久久国产越南 | 艹逼网| 久久新视频 | 欧美美乳 | 可以免费看的毛片 | 黄色成人免费看 | 日韩在线视频免费观看 | 在线播放亚洲 | 精品欧美一区二区在线观看 | 欧美一级在线观看 | 国产视频一二三区 | 日韩欧美三区 | 久久伊人精品 | 国产成人精品久久 | 亚洲天堂一区 | 99久久久国产精品 | 中文字幕日韩欧美 | 精品一区二区久久久久久久网站 | 国产成人免费 | 一级网站 | 成人欧美一区二区三区黑人孕妇 | 精品视频亚洲 | 欧美不卡一区二区 | 麻豆视频在线免费看 | 国产精品免费观看 | 亚洲成网站 | 亚洲国产精品久久人人爱 | 国产精品久久久久久亚洲调教 | 国产精品免费一区二区三区四区 | 国产精品免费av | 国产成人av一区二区三区 |