最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JS 實現(xiàn)緩存算法的示例(FIFO/LRU)

 更新時間:2018年03月20日 10:50:40   作者:RayLeo  
這篇文章主要介紹了JS 實現(xiàn)緩存算法的示例(FIFO/LRU),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

FIFO

最簡單的一種緩存算法,設(shè)置緩存上限,當(dāng)達到了緩存上限的時候,按照先進先出的策略進行淘汰,再增加進新的 k-v 。

使用了一個對象作為緩存,一個數(shù)組配合著記錄添加進對象時的順序,判斷是否到達上限,若到達上限取數(shù)組中的第一個元素key,對應(yīng)刪除對象中的鍵值。

/**
 * FIFO隊列算法實現(xiàn)緩存
 * 需要一個對象和一個數(shù)組作為輔助
 * 數(shù)組記錄進入順序
 */
class FifoCache{
  constructor(limit){
    this.limit = limit || 10
    this.map = {}
    this.keys = []
  }
  set(key,value){
    let map = this.map
    let keys = this.keys
    if (!Object.prototype.hasOwnProperty.call(map,key)) {
      if (keys.length === this.limit) {
        delete map[keys.shift()]//先進先出,刪除隊列第一個元素
      }
      keys.push(key)
    }
    map[key] = value//無論存在與否都對map中的key賦值
  }
  get(key){
    return this.map[key]
  }
}

module.exports = FifoCache

LRU

LRU(Least recently used,最近最少使用)算法。該算法的觀點是,最近被訪問的數(shù)據(jù)那么它將來訪問的概率就大,緩存滿的時候,優(yōu)先淘汰最無人問津者。

算法實現(xiàn)思路:基于一個雙鏈表的數(shù)據(jù)結(jié)構(gòu),在沒有滿員的情況下,新來的 k-v 放在鏈表的頭部,以后每次獲取緩存中的 k-v 時就將該k-v移到最前面,緩存滿的時候優(yōu)先淘汰末尾的。

雙向鏈表的特點,具有頭尾指針,每個節(jié)點都有 prev(前驅(qū)) 和 next(后繼) 指針分別指向他的前一個和后一個節(jié)點。

關(guān)鍵點:在雙鏈表的插入過程中要注意順序問題,一定是在保持鏈表不斷的情況下先處理指針,最后才將原頭指針指向新插入的元素,在代碼的實現(xiàn)中請注意看我在注釋中說明的順序注意點!

class LruCache {
  constructor(limit) {
    this.limit = limit || 10
    //head 指針指向表頭元素,即為最常用的元素
    this.head = this.tail = undefined
    this.map = {}
    this.size = 0
  }
  get(key, IfreturnNode) {
    let node = this.map[key]
    // 如果查找不到含有`key`這個屬性的緩存對象
    if (node === undefined) return
    // 如果查找到的緩存對象已經(jīng)是 tail (最近使用過的)
    if (node === this.head) { //判斷該節(jié)點是不是是第一個節(jié)點
      // 是的話,皆大歡喜,不用移動元素,直接返回
      return returnnode ?
        node :
        node.value
    }
    // 不是頭結(jié)點,鐵定要移動元素了
    if (node.prev) { //首先要判斷該節(jié)點是不是有前驅(qū)
      if (node === this.tail) { //有前驅(qū),若是尾節(jié)點的話多一步,讓尾指針指向當(dāng)前節(jié)點的前驅(qū)
        this.tail = node.prev
      }
      //把當(dāng)前節(jié)點的后繼交接給當(dāng)前節(jié)點的前驅(qū)去指向。
      node.prev.next = node.next
    }
    if (node.next) { //判斷該節(jié)點是不是有后繼
      //有后繼的話直接讓后繼的前驅(qū)指向當(dāng)前節(jié)點的前驅(qū)
      node.next.prev = node.prev
      //整個一個過程就是把當(dāng)前節(jié)點拿出來,并且保證鏈表不斷,下面開始移動當(dāng)前節(jié)點了
    }
    node.prev = undefined //移動到最前面,所以沒了前驅(qū)
    node.next = this.head //注意?。。?這里要先把之前的排頭給接到手?。。?!讓當(dāng)前節(jié)點的后繼指向原排頭
    if (this.head) {
      this.head.prev = node //讓之前的排頭的前驅(qū)指向現(xiàn)在的節(jié)點
    }
    this.head = node //完成了交接,才能執(zhí)行此步!不然就找不到之前的排頭啦!
    return IfreturnNode ?
      node :
      node.value
  }
  set(key, value) {
    // 之前的算法可以直接存k-v但是現(xiàn)在要把簡單的 k-v 封裝成一個滿足雙鏈表的節(jié)點
    //1.查看是否已經(jīng)有了該節(jié)點
    let node = this.get(key, true)
    if (!node) {
      if (this.size === this.limit) { //判斷緩存是否達到上限
        //達到了,要刪最后一個節(jié)點了。
        if (this.tail) {
          this.tail = this.tail.prev
          this.tail.prev.next = undefined
          //平滑斷鏈之后,銷毀當(dāng)前節(jié)點
          this.tail.prev = this.tail.next = undefined
          this.map[this.tail.key] = undefined
          //當(dāng)前緩存內(nèi)存釋放一個槽位
          this.size--
        }
        node = {
          key: key
        }
        this.map[key] = node
        if(this.head){//判斷緩存里面是不是有節(jié)點
          this.head.prev = node
          node.next = this.head
        }else{
          //緩存里沒有值,皆大歡喜,直接讓head指向新節(jié)點就行了
          this.head = node
          this.tail = node
        }
        this.size++//減少一個緩存槽位
      }
    }
    //節(jié)點存不存在都要給他重新賦值啊
    node.value = value
  }
}

module.exports = LruCache

具體的思路就是如果所要get的節(jié)點不是頭結(jié)點(即已經(jīng)是最近使用的節(jié)點了,不需要移動節(jié)點位置)要先進行平滑的斷鏈操作,處理好指針指向的關(guān)系,拿出需要移動到最前面的節(jié)點,進行鏈表的插入操作。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 全面解析JavaScript Module模式

    全面解析JavaScript Module模式

    這篇文章主要介紹了JavaScript Module模式的相關(guān)資料,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • JavaScript實現(xiàn)獲得所有兄弟節(jié)點的方法

    JavaScript實現(xiàn)獲得所有兄弟節(jié)點的方法

    這篇文章主要介紹了JavaScript實現(xiàn)獲得所有兄弟節(jié)點的方法,實例分析了javascript節(jié)點遍歷的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-07-07
  • JS基于正則表達式的替換操作(replace)用法示例

    JS基于正則表達式的替換操作(replace)用法示例

    這篇文章主要介紹了JS基于正則表達式的替換操作(replace)用法,結(jié)合具體實例形式詳細(xì)分析了replace函數(shù)的語法、參數(shù)及具體使用技巧,需要的朋友可以參考下
    2017-04-04
  • 通過js控制修改css變量的具體示例

    通過js控制修改css變量的具體示例

    在網(wǎng)頁開發(fā)中我們通常使用CSS來設(shè)置網(wǎng)頁的樣式,但是,在開發(fā)過程中,有時候我們需要根據(jù)不同的條件來動態(tài)修改樣式,這篇文章主要介紹了通過js控制修改css變量的具體示例,需要的朋友可以參考下
    2025-04-04
  • Javascript之高級數(shù)組API的使用實例

    Javascript之高級數(shù)組API的使用實例

    今天小編就為大家分享一篇關(guān)于Javascript之高級數(shù)組API的使用實例,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • JS中prototype的用法實例分析

    JS中prototype的用法實例分析

    這篇文章主要介紹了JS中prototype的用法,實例分析了JS中prototype的常見使用技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-03-03
  • JavaScript如何使用dhtmlXTreeObject的loadJSONObject繪制目錄樹

    JavaScript如何使用dhtmlXTreeObject的loadJSONObject繪制目錄樹

    這篇文章主要介紹了JavaScript如何使用dhtmlXTreeObject的loadJSONObject繪制目錄樹,需要引入dhtmlXTreeObject的css和js文件,這里還需要注意js的引用順序,本文給大家介紹的非常詳細(xì),需要的的朋友參考下吧
    2023-11-11
  • 微信小程序開發(fā)之實現(xiàn)心情記事本

    微信小程序開發(fā)之實現(xiàn)心情記事本

    這篇文章主要為大家詳細(xì)介紹了如何通過微信小程序開發(fā)一個簡單的心情記事本,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以和小編一起學(xué)習(xí)一下
    2023-01-01
  • js 彈出框 替代瀏覽器的彈出框

    js 彈出框 替代瀏覽器的彈出框

    js 彈出框 替代瀏覽器的彈出框,需要的朋友可以參考下。
    2010-10-10
  • 微信小程序?qū)崿F(xiàn)上傳圖片的功能

    微信小程序?qū)崿F(xiàn)上傳圖片的功能

    這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)上傳圖片的功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08

最新評論

卢氏县| 上虞市| 津市市| 青神县| 桐庐县| 哈尔滨市| 大埔区| 龙海市| 兴业县| 成武县| 北辰区| 六安市| 光泽县| 长垣县| 广西| 合山市| 祁门县| 盱眙县| 铜鼓县| 茶陵县| 台北市| 连南| 繁昌县| 平江县| 扶绥县| 双峰县| 灵台县| 太仓市| 浮山县| 观塘区| 瑞丽市| 呼伦贝尔市| 龙胜| 军事| 合川市| 波密县| 普格县| 台南市| 定南县| 巴马| 获嘉县|