日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

fifo算法_缓存算法FIFO、LFU、LRU

發布時間:2023/12/9 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 fifo算法_缓存算法FIFO、LFU、LRU 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

閱讀文本大概需要3分鐘。

0x01:FIFO算法

  FIFO(First in First out),先進先出。其實在操作系統的設計理念中很多地方都利用到了先進先出的思想,比如作業調度(先來先服務),為什么這個原則在很多地方都會用到呢?因為這個原則簡單、且符合人們的慣性思維,具備公平性,并且實現起來簡單,直接使用數據結構中的隊列即可實現。

  在FIFO Cache設計中,核心原則就是:如果一個數據最先進入緩存中,則應該最早淘汰掉。也就是說,當緩存滿的時候,應當把最先進入緩存的數據給淘汰掉。在FIFO Cache中應該支持以下操作;

  get(key):如果Cache中存在該key,則返回對應的value值,否則,返回-1;

  set(key,value):如果Cache中存在該key,則重置value值;如果不存在該key,則將該key插入到到Cache中,若Cache已滿,則淘汰最早進入Cache的數據。

  舉個例子:假如Cache大小為3,訪問數據序列為set(1,1),set(2,2),set(3,3),set(4,4),get(2),set(5,5)

  則Cache中的數據變化為:

  (1,1)?????????????????????????????? set(1,1)

  (1,1) (2,2)?????????????????????? set(2,2)

  (1,1) (2,2) (3,3)?????????????? set(3,3)

  (2,2) (3,3) (4,4)?????????????? set(4,4)

  (2,2) (3,3) (4,4)?????????????? get(2)

  (3,3) (4,4) (5,5)?????????????? set(5,5)

?  那么利用什么數據結構來實現呢?

  下面提供一種實現思路:

  利用一個雙向鏈表保存數據,當來了新的數據之后便添加到鏈表末尾,如果Cache存滿數據,則把鏈表頭部數據刪除,然后把新的數據添加到鏈表末尾。在訪問數據的時候,如果在Cache中存在該數據的話,則返回對應的value值;否則返回-1。如果想提高訪問效率,可以利用hashmap來保存每個key在鏈表中對應的位置。

0x02:LFU算法

  LFU(Least Frequently Used)最近最少使用算法。它是基于“如果一個數據在最近一段時間內使用次數很少,那么在將來一段時間內被使用的可能性也很小”的思路。

  注意LFU和LRU算法的不同之處,LRU的淘汰規則是基于訪問時間,而LFU是基于訪問次數的。舉個簡單的例子:

  假設緩存大小為3,數據訪問序列為set(2,2),set(1,1),get(2),get(1),get(2),set(3,3),set(4,4),

  則在set(4,4)時對于LFU算法應該淘汰(3,3),而LRU應該淘汰(1,1)。

  那么LFU Cache應該支持的操作為:

  get(key):如果Cache中存在該key,則返回對應的value值,否則,返回-1;

  set(key,value):如果Cache中存在該key,則重置value值;如果不存在該key,則將該key插入到到Cache中,若Cache已滿,則淘汰最少訪問的數據。

  為了能夠淘汰最少使用的數據,因此LFU算法最簡單的一種設計思路就是 利用一個數組存儲 數據項,用hashmap存儲每個數據項在數組中對應的位置,然后為每個數據項設計一個訪問頻次,當數據項被命中時,訪問頻次自增,在淘汰的時候淘汰訪問頻次最少的數據。這樣一來的話,在插入數據和訪問數據的時候都能達到O(1)的時間復雜度,在淘汰數據的時候,通過選擇算法得到應該淘汰的數據項在數組中的索引,并將該索引位置的內容替換為新來的數據內容即可,這樣的話,淘汰數據的操作時間復雜度為O(n)。

  另外還有一種實現思路就是利用 小頂堆+hashmap,小頂堆插入、刪除操作都能達到O(logn)時間復雜度,因此效率相比第一種實現方法更加高效。

  如果哪位朋友有更高效的實現方式(比如O(1)時間復雜度),不妨探討一下,不勝感激。

0x03:LRU算法

LRU算法的設計原則是:如果一個數據在最近一段時間沒有被訪問到,那么在將來它被訪問的可能性也很小。也就是說,當限定的空間已存滿數據時,應當把最久沒有被訪問到的數據淘汰。

而用什么數據結構來實現LRU算法呢?可能大多數人都會想到:用一個數組來存儲數據,給每一個數據項標記一個訪問時間戳,每次插入新數據項的時候,先把數組中存在的數據項的時間戳自增,并將新數據項的時間戳置為0并插入到數組中。每次訪問數組中的數據項的時候,將被訪問的數據項的時間戳置為0。當數組空間已滿時,將時間戳最大的數據項淘汰。

  這種實現思路很簡單,但是有什么缺陷呢?需要不停地維護數據項的訪問時間戳,另外,在插入數據、刪除數據以及訪問數據時,時間復雜度都是O(n)。

  那么有沒有更好的實現辦法呢?

  那就是利用鏈表和hashmap。當需要插入新的數據項的時候,如果新數據項在鏈表中存在(一般稱為命中),則把該節點移到鏈表頭部,如果不存在,則新建一個節點,放到鏈表頭部,若緩存滿了,則把鏈表最后一個節點刪除即可。在訪問數據的時候,如果數據項在鏈表中存在,則把該節點移到鏈表頭部,否則返回-1。這樣一來在鏈表尾部的節點就是最近最久未訪問的數據項。

  總結一下:根據題目的要求,LRU Cache具備的操作:

  1)set(key,value):如果key在hashmap中存在,則先重置對應的value值,然后獲取對應的節點cur,將cur節點從鏈表刪除,并移動到鏈表的頭部;若果key在hashmap不存在,則新建一個節點,并將節點放到鏈表的頭部。當Cache存滿的時候,將鏈表最后一個節點刪除即可。

  2)get(key):如果key在hashmap中存在,則把對應的節點放到鏈表頭部,并返回對應的value值;如果不存在,則返回-1。

推薦閱讀

Spring Boot 最流行的 16 條實踐

SSM框架的面試常見問題

【分布式】緩存穿透、緩存雪崩,緩存擊穿解決方案

阿里P7給出的一份超詳細 Spring Boot 知識清單

關注我每天進步一點點

你點的每個在看,我都認真當成了喜歡

總結

以上是生活随笔為你收集整理的fifo算法_缓存算法FIFO、LFU、LRU的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。