LRU算法與LFU算法

知識點:

LRU是Least Recently Used的縮寫,意思是最近最少使用,它是一種Cache替換算法
Cache的容量有限,因此當Cache的容量用完后,而又有新的內容需要添加進來時, 就需要挑選
并舍棄原有的部分內容,從而騰出空間來放新內容。LRU Cache 的替換原則就是將最近最少使用
的內容替換掉。其實,LRU譯成最久未使用會更形象, 因為該算法每次替換掉的就是一段時間內
最久沒有使用過的內容

?

LRU本質就是一個頁面置換算法,關鍵就是如何實現get()和put()函數O(1)時間復雜度

具體內容請打開leedcode上面這題:

146. LRU 緩存 - 力扣(LeetCode)

如何實現O(1),關鍵在于鏈表和哈希的使用,我來結合代碼講解:

//首先,定義一個capacity、list和unordered_map成員變量,注意的是_hashmp存放的第二個參數為list迭代器,list存放的是pair類型,first為key,second為value
//其次:實現put函數,如果存在,我們只需要更新器內容,并放在鏈表的頭部(注:尾部是不使用的),但當我們put的是不存在的,需要判斷容量是否滿足,是否需要刪除list尾部,然后再插入到鏈表的頭部,更新——_hashmp注意放的是iterator
//最后,實現get函數,不存在返回-1,否則,找到該value,然后將其提前保存放入list頭部,再將其原位置刪除,同時更新hash中迭代器位置
class LRUCache {
public:LRUCache(int capacity) {_capacity = capacity;}//O(1):int get(int key) {//通過key得到value,否則返回-1//去哈希中查找auto hashit = _hashmap.find(key);if(hashit == _hashmap.end()){//未找到return -1;}else{//找到auto listit = hashit->second;//更新該節點的使用情況pair<int,int> kv = *listit;_list.erase(listit);_list.push_front(kv);//更新哈希_hashmap[key] = _list.begin();return kv.second;}}//O(1):void put(int key, int value) {//存在更新,不存在插入//判斷是否存在auto hashit = _hashmap.find(key);//注意:hashit是迭代器if(hashit == _hashmap.end()){//不存在,插入,注意capacityif(_list.size() == _capacity){//刪除最近未使用的_hashmap.erase(_list.back().first);_list.pop_back();}//插入到鏈表頭部+更新哈希_list.push_front(make_pair(key,value));_hashmap[key] = _list.begin();}else{//存在,更新數據并且放在鏈表頭部,我們尾部是最近未使用數據//獲取list中迭代器位置auto listit = hashit->second;//更新KVpair<int,int> kv = *listit;kv.second = value;//將鏈表中該節點位置放入頭部_list.erase(listit);_list.push_front(kv);//更新哈希_hashmap[key] = _list.begin();}}
private:int _capacity;//容量list<pair<int,int>> _list;unordered_map<int,list<pair<int,int>>::iterator> _hashmap;
};

LRU面試不算經常考察的內容,但是也需要我們會實現到O(1)的復雜度

補充:

現在還存在面試常考的另一種算法LFU算法

該算法是通過一個count記錄來處理最少使用的情況,下面聯系leedcode例題來講解:

460. LFU 緩存 - 力扣(LeetCode)

實現過程:

class LFUCache {
public:LFUCache(int capacity) {_capacity = capacity;}int get(int key) {auto hashit = _hashmp.find(key);if (hashit == _hashmp.end()) return -1;// 獲取當前節點并更新頻率auto listit = hashit->second;auto kcv = *listit;_list.erase(listit);  // 先移除舊節點// 更新頻率并重新插入到正確位置kcv.second.first++;auto new_it = insertIntoSortedList(kcv);_hashmp[key] = new_it;return kcv.second.second;}void put(int key, int value) {auto hashit = _hashmp.find(key);if (hashit == _hashmp.end()) {// 緩存已滿,淘汰頻率最低且最久未使用的節點if (_list.size() >= _capacity) {_hashmp.erase(_list.back().first);_list.pop_back();}// 插入新節點(頻率=1)auto kcv = make_pair(key, make_pair(1, value));auto new_it = insertIntoSortedList(kcv);_hashmp[key] = new_it;} else {// 更新現有節點(邏輯同get)auto listit = hashit->second;auto kcv = *listit;_list.erase(listit);kcv.second.first++;kcv.second.second = value;  // 更新valueauto new_it = insertIntoSortedList(kcv);_hashmp[key] = new_it;}}private:// 輔助函數:將節點按頻率和訪問順序插入到鏈表list<pair<int, pair<int, int>>>::iterator insertIntoSortedList(const pair<int, pair<int, int>>& kcv) {// 遍歷鏈表,找到第一個頻率 <= 當前節點頻率的位置for (auto it = _list.begin(); it != _list.end(); ++it) {if (it->second.first <= kcv.second.first) {return _list.insert(it, kcv);  // 插入到該位置前}}// 如果所有節點頻率都更低,插入到末尾return _list.insert(_list.end(), kcv);}int _capacity;list<pair<int, pair<int, int>>> _list;  // (key, (count, value))unordered_map<int, list<pair<int, pair<int, int>>>::iterator> _hashmp;
};

通過list和unordered_map來實現,但是需要兩個pair(重點),另外就是就是insert和erase操作使用,希望對大家有幫助!!!

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

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

相關文章

目標檢測公開數據集全解析:從經典到前沿

目標檢測公開數據集全解析&#xff1a;從經典到前沿 一、引言 目標檢測&#xff08;Object Detection&#xff09;是計算機視覺領域的核心任務之一&#xff0c;旨在在圖像或視頻中識別并定位感興趣的物體。與圖像分類不同&#xff0c;目標檢測不僅需要判斷物體的類別&#xf…

數據備份與進程管理

一、數據備份1.Linux服務器中需要備份的數據&#xff08;1&#xff09;Linux系統重要數據&#xff1a;/root/目錄&#xff0c;/home/目錄&#xff0c;/etc/目錄&#xff08;2&#xff09;安裝服務的數據&#xff1a;Apache&#xff08;配置文件&#xff0c;網頁主目錄&#xff…

docker volume卷入門教程

1. 基礎概念 Docker卷是專門用于持久化容器數據的存儲方案&#xff0c;獨立于容器生命周期。其核心優勢包括&#xff1a; 數據持久化&#xff1a;容器刪除后數據仍保留跨容器共享&#xff1a;多個容器可訪問同一卷備份與遷移&#xff1a;支持直接復制卷數據驅動支持&#xff1a…

計算機網絡——協議

1. 計算機網絡分層1.1 OSI 7層模型應用層表示層會話層傳輸層網絡層數據鏈路層物理層1.2 TCP/IP 4 層模型應用層運輸層網際層網絡接口層1.3 5層體系機構應用層傳輸層網絡層數據鏈路層物理層2. 應用層協議2.1 HTTP協議2.1.1 基本介紹HTTP&#xff08;HyperText Transfer Protocol…

【React】hooks 中的閉包陷阱

在 React Hooks 中的 閉包陷阱&#xff08;Closure Trap&#xff09;在 useEffect、事件回調、定時器等場景里很常見。1. 閉包陷阱是什么 當你在函數組件里定義一個回調&#xff08;比如事件處理函數&#xff09;&#xff0c;這個回調會捕獲當時渲染時的變量值。如果后面狀態更…

校園快遞小程序(騰訊地圖API、二維碼識別、Echarts圖形化分析)

&#x1f388;系統亮點&#xff1a;騰訊地圖API、二維碼識別、Echarts圖形化分析&#xff1b;一.系統開發工具與環境搭建1.系統設計開發工具后端使用Java編程語言的Spring boot框架 項目架構&#xff1a;B/S架構 運行環境&#xff1a;win10/win11、jdk17小程序&#xff1a; 技術…

Python網絡爬蟲(二) - 解析靜態網頁

文章目錄一、網頁解析技術介紹二、Beautiful Soup庫1. Beautiful Soup庫介紹2. Beautiful Soup庫幾種解析器比較3. 安裝Beautiful Soup庫3.1 安裝 Beautiful Soup 43.2 安裝解析器4. Beautiful Soup使用步驟4.1 創建Beautiful Soup對象4.2 獲取標簽4.2.1 通過標簽名獲取4.2.2 通…

【Linux基礎知識系列】第九十四篇 - 如何使用traceroute命令追蹤路由

在網絡環境中&#xff0c;了解數據包從源主機到目標主機的路徑是非常重要的。這不僅可以幫助我們分析網絡連接問題&#xff0c;還可以用于診斷網絡延遲、丟包等問題。traceroute命令是一個強大的工具&#xff0c;它能夠追蹤數據包在網絡中的路徑&#xff0c;顯示每一跳的延遲和…

達夢數據閃回查詢-快速恢復表

Time:2025/08/12Author:skatexg一、環境說明DM數據庫&#xff1a;DM8.0及以上版本二、適用場景研發在誤操作或變更數據后&#xff0c;想馬上恢復表到某個時間點&#xff0c;可以通過閃回查詢功能快速實現&#xff08;通過全量備份恢復時間長&#xff0c;成本高&#xff09;三、…

力扣(LeetCode) ——225 用隊列實現棧(C語言)

題目&#xff1a;用隊列實現棧示例1&#xff1a; 輸入&#xff1a; [“MyStack”, “push”, “push”, “top”, “pop”, “empty”] [[], [1], [2], [], [], []] 輸出&#xff1a; [null, null, null, 2, 2, false] 解釋&#xff1a; MyStack myStack new MyStack(); mySta…

微軟推出AI惡意軟件檢測智能體 Project Ire

開篇 在8月5號&#xff0c;微軟研究院發布了一篇博客文章&#xff0c;在該篇博客中推出了一款名為Project Ire的AI Agent。該Agent可以在無需人類協助的情況下&#xff0c;自主分析和分類二進制文件。它可以在無需了解二進制文件來源或用途的情況下&#xff0c;對文件進行完全的…

哪些對會交由SpringBoot容器管理?

在 Spring Boot 中,交由容器管理的對象通常稱為“Spring Bean”,這些對象的創建、依賴注入、生命周期等由 Spring 容器統一管控。以下是常見的會被 Spring Boot 容器管理的對象類型及識別方式: 一、通過注解聲明的組件(最常見) Spring Boot 通過類級別的注解自動掃描并注…

Android POS應用在android運行常見問題及解決方案

概述 本文檔記錄了在Android POS應用開發過程中遇到的兩個關鍵問題及其解決方案&#xff1a; UnsatisfiedLinkError: couldnt find "libnative.so" 錯誤ActivityNotFoundException 錯誤商戶信息一致性檢查繞過 問題1&#xff1a;UnsatisfiedLinkError - libnative.so…

基于SpringBoot的旅游網站系統

1. 項目簡介 旅游線路管理系統是一個基于Spring Boot的在線旅游服務平臺&#xff0c;提供旅游線路展示、分類、預訂、訂單管理等功能。系統包含前臺用戶界面和后臺管理模塊&#xff0c;支持用戶注冊登錄、線路瀏覽、收藏、下單支付、客服咨詢等核心功能。管理員可管理線路信息、…

CVPR 2025 | 機器人操控 | RoboGround:用“掩碼”中介表示,讓機器人跨場景泛化更聰明

點擊關注gongzhonghao【計算機sci論文精選】1.導讀1.1論文基本信息論文標題&#xff1a;ROBOGROUND: Robotic Manipulation with Grounded Vision-Language Priors作者&#xff1a;Haifeng Huang, Xinyi Chen, Hao Li&#xff0c; Xiaoshen Han, Yilun Chen, Tai Wang, Zehan W…

構建Node.js單可執行應用(SEA)的方法

如果為了降低部署復雜度&#xff0c;可以考慮使用vercel/ncc。除非有特別理由&#xff0c;不建議使用SEA。1. 環境準備1.1. 基礎要求Node.js: > 19.0.0 (推薦最新LTS版本)1.2. 安裝依賴npm install postject typescript1.3. 驗證環境node -v # 確認版本 > 19 ts…

Java19 Integer 位操作精解:compress與expand《Hacker‘s Delight》(第二版,7.4節)

compress(int i, int mask) 這個方法是Java 19中新增的一個強大的位操作函數。compress 方法的核心功能可以理解為 “按位過濾和壓縮” 。過濾 (Filter): 它使用 mask&#xff08;掩碼&#xff09;作為過濾器。對于輸入整數 i&#xff0c;只有那些在 mask 中對應位為 1 的比特才…

minio部署和雙機熱備

安裝單機版MinIO&#xff08;準備2臺機器A、B,A、B服務器操作一致&#xff09;切換目錄并下載MinIO二進制文件cd /usr/local/bin wget https://dl.minio.org.cn/server/minio/release/linux-amd64/minio chmod x minio編輯配置文件vi /etc/default/minio.confMINIO_VOLUMES&quo…

【Java】 Java 21 革命性升級:虛擬線程與結構化并發的深度實踐指南

還在為高昂的AI開發成本發愁?這本書教你如何在個人電腦上引爆DeepSeek的澎湃算力! Java 21 作為 Oracle JDK 的長期支持版本,引入了多項革命性特性,其中虛擬線程(Virtual Threads)和結構化并發(Structured Concurrency)尤為突出。這些特性旨在解決傳統線程模型在高并發…

Apache IoTDB 全場景部署:基于 Apache IoTDB 的跨「端-邊-云」的時序數據庫 DB+AI

Apache IoTDB 全場景部署&#xff1a;基于 Apache IoTDB 的跨「端-邊-云」的時序數據庫 DBAI 文章目錄Apache IoTDB 全場景部署&#xff1a;基于 Apache IoTDB 的跨「端-邊-云」的時序數據庫 DBAIApache IoTDB 介紹Docker部署指導企業版數據庫配套工具 WorkbenchTimechoDB&…