理解和實現 LFU 緩存置換算法

引言

在計算機科學中,緩存是一種重要的技術,用于提高數據訪問速度和系統性能。然而,由于緩存空間有限,當緩存滿了之后,就需要一種智能的策略來決定哪些數據應該保留,哪些應該被淘汰。LFU(Least Frequently Used,最少使用)算法就是一種常見的緩存淘汰策略,它基于數據項的訪問頻率來進行優化管理。

LFU算法簡介

LFU算法的核心思想是優先淘汰那些訪問頻率最低的數據項。在緩存達到容量限制時,LFU算法會移除那些被訪問次數最少的緩存條目。如果多個條目的訪問次數相同,則根據它們最早被訪問的時間進行決策,優先刪除最早被訪問的條目。

LFU算法的工作原理

LFU算法通常需要兩種數據結構來實現:

哈希表:提供O(1)時間復雜度的數據訪問和插入。此時哈希表需要兩個,一個記錄key和當前節點的映射,一個記錄頻率和節點的映射
雙向鏈表:維護數據項的使用順序,最近使用的在頭部,最久未使用的在尾部。

數據訪問和插入的流程如下:

獲取數據(Get):從緩存中獲取數據,如果數據存在(緩存命中),則更新數據使用的頻率,也就是頻率+1,同時要刪除當前節點之前對應的頻率映射;如果數據不存在(緩存未命中),返回 -1。
插入數據(Put):將數據放入緩存,如果數據已經存在,則更新數據值并更新數據使用的頻率;如果數據不存在,則將數據插入放入緩存中,并將最低頻率設置為1。如果緩存已滿,首先需要移除緩存中的元素,然后再插入。

LFU算法的實現

import java.util.HashMap;public class LFUCache {static class Node{int key, value, freq = 1;Node prev, next;Node(int key, int value){this.key = key;this.value = value;}}// 鍵到節點的映射private HashMap<Integer, Node> keyToNode = new HashMap<>();// 頻率到虛擬頭節點的映射private HashMap<Integer, Node> freqToDummy = new HashMap<>();// 最小訪問頻率private int minFreq;// 容量private int capacity;public LFUCache(int capacity) {this.capacity = capacity;}private Node newList() {Node dummy = new Node(0, 0);dummy.prev = dummy;dummy.next = dummy;return dummy;}/*** 根據鍵獲取值。* 該方法首先嘗試從keyToNode映射中獲取給定鍵對應的節點。如果節點不存在,說明該鍵不存在于數據結構中,方法將返回-1。* 如果節點存在,則該方法會執行刪除操作(del)和頻率更改操作(changeFreq),然后再返回節點的值。* 這種設計可能是為了在獲取值的同時,根據獲取情況動態調整數據結構,例如實現一種基于頻率的緩存淘汰策略。** @param key 需要獲取值的鍵。* @return 鍵對應的值,如果鍵不存在,則返回-1。*/public int get(int key) {// 嘗試從映射中獲取給定鍵對應的節點。Node node = keyToNode.get(key);// 如果節點不存在,說明鍵不存在于數據結構中,返回-1。if(node == null) return -1;// 修改節點的頻率信息,changeFreq(node);// 返回節點的值。return node.value;}/*** 插入一個鍵值對到緩存中。* 如果鍵已經存在,則更新其值,并根據更新后的頻率進行調整。* 如果緩存已滿,則移除最低頻率的鍵值對,并插入新的鍵值對。** @param key 插入或更新的鍵。* @param value 插入或更新的值。*/public void put(int key, int value) {// 嘗試從映射中獲取現有的節點Node node = keyToNode.get(key);if(node != null){// 如果節點存在,更新其值,并準備進行頻率更新操作node.value = value;changeFreq(node);return;}// 如果緩存已滿,需要移除最低頻率的節點以騰出空間if(keyToNode.size() == capacity){Node cur = freqToDummy.get(minFreq);Node delNode = cur.prev;keyToNode.remove(delNode.key);del(delNode);if(cur.prev == cur) freqToDummy.remove(minFreq);}// 創建新節點,并插入到映射和頻率鏈表中node = new Node(key, value);keyToNode.put(key, node);insert(1, node);minFreq = 1;}/*** 修改節點的頻率。* 此方法用于更新給定節點的頻率,并相應地調整頻率列表和最小頻率的值。* 如果更新后的頻率導致原有的頻率列表頭部節點成為一個孤立節點(即它的前向和后向指針都指向自己),* 則該節點將從頻率列表中移除,并且如果該頻率原本是最低頻率,則最小頻率值將增加。* 最后,使用更新后的頻率將節點插入到頻率列表的適當位置。** @param node 需要更新頻率的節點。*/void changeFreq(Node node){// 1、先刪除節點del(node);// 根據當前節點的頻率獲取頻率鏈表的頭部節點Node cur = freqToDummy.get(node.freq);// 檢查當前頻率的鏈表是否為空(即頭部節點的前向指針是否指向自己)if(cur.prev == cur){// 如果鏈表為空,則從映射中移除該頻率,并檢查是否需要調整最小頻率值freqToDummy.remove(node.freq);if(minFreq == node.freq){minFreq++;}}// 3、插入到新位置insert(++node.freq, node);}/*** 將給定節點插入到特定頻率鏈表中。* 此函數假設頻率對應的鏈表已經存在,或者如果不存在,則會創建一個新的鏈表。* 插入操作在鏈表的頭部進行,以保持節點按頻率排序。** @param key 節點的鍵值,用于確定節點應插入到哪個頻率鏈表。* @param node 要插入的節點。*/void insert(int key, Node node){// 根據頻率獲取或創建對應的頻率鏈表的頭節點。// 獲取頻率的頭節點Node cur = freqToDummy.computeIfAbsent(key, k -> newList());node.prev = cur;node.next = cur.next;cur.next.prev = node;cur.next = node;}/*** 從雙向鏈表中刪除給定節點。* 此函數不返回任何值,因為它操作的是鏈表的內部結構。* 它接受一個參數 node,該參數是需要被刪除的節點。** @param node 需要被刪除的節點。*/void del(Node node){/* 將給定節點的前一個節點的next指針指向給定節點的后一個節點,從而在鏈表中向前斷開給定節點。 */node.next.prev = node.prev;/* 將給定節點的后一個節點的prev指針指向給定節點的前一個節點,從而在鏈表中向后斷開給定節點。 */node.prev.next = node.next;}}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/34971.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/34971.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/34971.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

FLASH閃存

FLASH閃存 程序現象&#xff1a; 1、讀寫內部FLASH 這個代碼的目的&#xff0c;就是利用內部flash程序存儲器的剩余空間&#xff0c;來存儲一些掉電不丟失的參數。所以這里的程序是按下K1變換一下測試數據&#xff0c;然后存儲到內部FLASH&#xff0c;按下K2把所有參數清0&…

找不到mfc140u.dll怎么修復,mfc140u.dll丟失的多種修復方法

計算機丟失mfc140u.dll文件會導致依賴該文件的軟件無法正常運行。mfc140u.dll是Microsoft Visual C 2015的可再發行組件之一&#xff0c;它屬于Microsoft Foundation Class (MFC) 庫&#xff0c;許多使用MFC開發的程序需要這個DLL文件來正確執行。丟失了mfc140u.dll文件。會導致…

無人機無刷電機理論教學培訓課程

本文檔為一份關于Brushless電機理論的詳細教程&#xff0c;由TYTO Robotics編制&#xff0c;旨在幫助用戶理解brushless電機的工作原理、特性以及如何通過實驗測定其關鍵參數Kv和Kt。文檔首先介紹了brushless電機的基本組成&#xff0c;包括靜止的定子和旋轉的轉子&#xff0c;…

AR增強現實在橋梁工程專業課堂上的應用

橋梁工程專業課堂上應用增強現實技術具有多方面的優勢。首先&#xff0c;增強現實技術能夠提供更加直觀、生動、真實的橋梁工程學習環境&#xff0c;使學生能夠更好地理解和掌握橋梁工程的基本原理和設計方法。其次&#xff0c;增強現實技術能夠提供更加豐富的橋梁工程案例和實…

考研數學|線代零基礎,聽誰的課比較合適?

線性代數是數學的一個重要分支&#xff0c;對于考研的學生來說&#xff0c;掌握好這門課程是非常關鍵的。由于你之前沒有聽過線性代數課&#xff0c;選擇一個合適的課程和老師就顯得尤為重要。 以下是一些建議&#xff0c;希望能幫助你找到合適的課程資源。 首先&#xff0c;…

Hadoop3:MapReduce中的ETL(數據清洗)

一、概念說明 “ETL&#xff0c;是英文Extract-Transform-Load的縮寫&#xff0c;用來描述將數據從來源端經過抽取&#xff08;Extract&#xff09;、轉換&#xff08;Transform&#xff09;、加載&#xff08;Load&#xff09;至目的端的過程。ETL一詞較常用在數據倉庫&#…

python學習 - 設計模式 - 狀態模式

大話設計模式 設計模式——狀態模式 狀態模式(State Pattern):當一個對象的內在狀態改變時允許改變其行為&#xff0c;這個對象看起來像是改變了其類 應用場景:當控制一個對象的狀態轉換的條件表達式過于復雜時,把狀態的判斷邏輯轉移到表示不同狀態的一系列類當中,可以把復雜的…

LED顯示屏的點間距越小越好嗎

引言 在LED顯示屏市場日趨成熟的同時&#xff0c;小間距顯示屏成為了許多用戶的首選。然而&#xff0c;點間距真的是越小越好嗎&#xff1f;本文將探討這一問題&#xff0c;并提供全面的選購指南。 點間距&#xff1a;并非越小越好 小間距顯示屏因其精細的顯示效果而備受青睞。…

剪輯如何剪輯制作視頻短視頻剪輯學習怎么學,難嗎?

工欲善其事必先利其器&#xff0c;有一個好的工具能讓你的工作如魚得水&#xff0c;果你想在短視頻中制作精良的視頻&#xff0c;你就考慮電腦制作軟件了。果你想制作精良的視頻&#xff0c;你就考慮電腦制作軟件了。 如何找到剪輯軟件了&#xff1f;你可以直接去軟件的官方。你…

KT6368A-sop8藍牙主機芯片獲取電動車胎壓傳感器數據功能

KT6368A藍牙芯片新增主機模式&#xff0c;掃描周邊的胎壓傳感器&#xff0c;這里扮演的角色就是觀察者。因為測試胎壓傳感器&#xff0c;發現它的廣播模式可發現&#xff0c;不可連接 胎壓傳感器部分的手冊說明如下&#xff0c;關于藍牙部分的協議 實際藍牙芯片收到的數據&…

國密算法SM1 SM2 SM3 SM4 SM9

一、概述 SM1-無具體實現 SM1作為一種對稱加密算法&#xff0c;由于其算法細節并未公開&#xff0c;且主要在中國國內使用&#xff0c;因此在國際通用的加密庫&#xff08;如Bouncy Castle&#xff09;中并不直接支持SM1算法。 SM1算法的具體實現涉及國家密碼管理局的規范&…

Studying-代碼隨想錄訓練營day20| 235.二叉搜索樹的最近公共祖先、701.二叉搜索樹中的插入操作、450.刪除二叉搜索樹中的節點

第二十天&#xff0c;二叉樹part07&#xff0c;二叉樹搜索樹加油加油&#x1f4aa; 目錄 235.二叉搜索樹的最近公共祖先 701.二叉搜索樹中的插入操作 450.刪除二叉搜索樹中的節點 拓展&#xff1a;普通二叉樹的刪除方式 總結 235.二叉搜索樹的最近公共祖先 文檔講解&…

潔凈室(區)浮游菌檢測標準操作規程及GB/T 16292-2010測試方法解讀

潔凈室(區)空氣中浮游菌的檢測。潔凈區浮游菌檢測是一種評估和控制潔凈區(如實驗室、生產車間等)內空氣質量的方法。這種檢測的目的是通過測量空氣中的微生物(即浮游菌)數量&#xff0c;來評估潔凈區的清潔度或污染程度。下面中邦興業小編帶大家詳細看下如何進行浮游菌采樣檢測…

RK3568技術筆記九 編譯Linux詳細介紹

在編譯前需要按照前面的方法始化編譯環境&#xff0c;否則會導致編譯失敗&#xff08;若配置過則無需重復配置&#xff09;。 全自動編譯包含所有鏡像編譯&#xff0c;包括&#xff1a;uboot編譯、Kernel編譯、Recovey編譯、文件系統編譯、編譯完成鏡像的更新與打包。 按照前面…

閱讀筆記——《Large Language Model guided Protocol Fuzzing》

【參考文獻】Meng R, Mirchev M, Bhme M, et al. Large language model guided protocol fuzzing[C]//Proceedings of the 31st Annual Network and Distributed System Security Symposium (NDSS). 2024.&#xff08;CCF A類會議&#xff09;【注】本文僅為作者個人學習筆記&a…

【附精彩文章合輯】當談到程序的“通用性”與“過度設計”的困境時,我們可以通過一些具體的例子來更直觀地闡述這些解決方案

當談到程序的“通用性”與“過度設計”的困境時&#xff0c;我們可以通過一些具體的例子來更直觀地闡述這些解決方案。以下是一些示例&#xff1a; 一、明確需求與目標 例子1&#xff1a;在線購物平臺 需求分析&#xff1a;平臺需要支持用戶注冊、登錄、瀏覽商品、下單購買、…

2024ciscn 華東北awdp pwn部分wp

pwn1 break 很簡單&#xff0c;棧可執行。 先格式化字符串泄露出棧地址和canary&#xff0c;然后稍稍布置一下打orw就行 沙盒和沒有一樣 from pwn import *context(archamd64, oslinux)if __name__ __main__:# io remote(192.47.1.39, 80)io remote(192.168.142.137, 123…

初階 《操作符詳解》 10. 逗號表達式

10. 逗號表達式 exp1, exp2, exp3, …expN 注&#xff1a; 1.逗號表達式&#xff0c;就是用逗號隔開的多個表達式 2.逗號表達式&#xff0c;從左向右依次執行&#xff0c;整個表達式的結果是最后一個表達式的結果 代碼1 #include <stdio.h> int main() {int a 1;int b…

【Qt6.3 基礎教程 19】 設計直觀用戶界面(UI):Qt應用界面設計原則

文章目錄 前言理解用戶需求界面的簡潔性一致性反饋利用布局管理美化你的應用結論 前言 用戶界面(UI)設計對于任何軟件項目的成功至關重要&#xff0c;因為它是用戶與您的應用之間交流的橋梁。在Qt環境中&#xff0c;擁有一套清晰和直觀的UI設計原則&#xff0c;將有助于您創建…

解決ubuntu18.04 安裝vscode 報依賴庫錯誤,以及打不開終端的問題。

其實很簡單&#xff0c;ubuntu18.04太老了&#xff0c;官網最新版本的vscode對ubuntu18.04會有些依賴庫的問題。 一頓查資料后發現2023.11月的1.85版本正常使用&#xff0c;于是完美解決。 下載鏈接 Visual Studio Code November 2023 點擊這里下載。 下載完成&#xff0c;…