一文徹底搞懂基于數組和鏈表分別實現LRU算法

文章目錄

  • 1. LRU算法
  • 2. 基于數組實現LRU算法
  • 3. 基于鏈表實現LRU算法

1. LRU算法

常見的緩存淘汰策略有三種,分別是:先進先出策略FIFO(First In,First Out)、最少使用策略LFU(Least Frequently Used)、最近最少使用策略LRU(Least Recently Used)

  • 先進先出策略(FIFO):即最先進入緩存的數據最先被淘汰。這種策略類似于隊列的工作方式,新數據加入到隊列的尾部,而最先進入隊列的數據會被淘汰。
  • 最少使用策略(LFU):即最少被訪問的數據最先被淘汰。LFU策略根據數據的訪問頻率來決定淘汰順序,訪問次數最少的數據會被優先淘汰。
  • 最近最少使用策略(LRU):即最近最少被訪問的數據最先被淘汰。LRU策略根據數據的訪問時間來決定淘汰順序,最近最久未被訪問的數據會被優先淘汰。

LRU算法的工作原理:

  1. 首先,我們定義一個容量為4的整型數組來模擬緩存,初始狀態數組為空
  2. 我們開始向數組中查詢數據,如果數據存在就返回,數據不存在就插入數據
    2.1 查詢數據1:由于緩存為空,將數據1插入到數組頭部(下標0)
    2.2 查詢數據2:由于緩存中已有數據1,根據LRU算法,將數據2插入到數組頭部,將原來的數據1向后位移,數組中的數據是2、1
    2.3 查詢數據3和4:類似地,數據3和4被插入到數組的頭部,數組中的數據變為4、3、2、1,此時數組達到了緩存的最大容量
  3. 繼續訪問數據就有兩種方式
    3.1 訪問緩存中沒有的數據,比如5,那么由于此是數組已經滿了,所以根據LRU算法定義,我們把數組尾部的數據1剔除,然后把1之前的數據,都向右位移一位,此時數組是:null、4、3、2,然后再將數據5插入到數組的頭部,那么此時數組中的數據就是:5、4、3、2
    3.2 訪問緩存中已經有的數據,比如2,那么不管此時數組是否已經滿了,我們可以在數組中找到數據2,那么我們就先把數組中數據是2的數據刪除,然后把2之前的數據顯向右位移一位,此時數組中的數據是:null、4、3、1,然后我們再把數據2插入到數組的頭部之后,數組中的數據是:2、4、3、1

2. 基于數組實現LRU算法

import java.util.HashMap;
import java.util.Map;/*** 基于數組實現LRU算法*/
public class LRUBaseArray<T> {private static final int DEFAULT_CAPACITY = 8;private int capacity; // 緩存容量private int count; // 緩存中元素數量private T[] value; // 存放元素的數組,模擬緩存private Map<T, Integer> holder; // 存儲數據的位置public LRUBaseArray() {this(DEFAULT_CAPACITY);}public LRUBaseArray(int capacity) {this.capacity = capacity;value = (T[]) new Object[capacity];count = 0;holder = new HashMap<>(capacity);}/*** 訪問某個值,有的話更新到頭部,沒有的話嘗試插入到頭部** @param object 待插入的元素*/public void offer(T object) {if (object == null) {throw new IllegalArgumentException("緩存容器不支持null");}Integer index = holder.get(object);if (index == null) {if (isFull()) {removeAndCache(object);} else {cache(object);}} else {update(index);}}/*** 將新元素插入緩存頭部** @param object 待插入的元素*/private void cache(T object) {rightShift(count);value[0] = object;holder.put(object, 0);count++;}/*** 更新已存在元素的位置到緩存頭部** @param index 元素在緩存中的位置索引*/private void update(Integer index) {T target = value[index];rightShift(index);value[0] = target;holder.put(target, 0);}/*** 緩存滿的情況下,刪除尾部元素,并將新元素插入緩存頭部** @param object 待插入的元素*/private void removeAndCache(T object) {T key = value[--count];holder.remove(key);cache(object);}/*** 將數組中的元素向右移動一位** @param end 數組邊界*/public void rightShift(int end) {for (int i = end - 1; i >= 0; i--) {value[i + 1] = value[i];holder.put(value[i], i + 1);}}/*** 判斷緩存是否已滿** @return 緩存是否已滿*/private boolean isFull() {return count == capacity;}@Overridepublic String toString() {StringBuilder sb = new StringBuilder();for (int i = 0; i < count; i++) {sb.append(value[i]);sb.append(" ");}return sb.toString();}public static void main(String[] args) {LRUBaseArray<Integer> lru = new LRUBaseArray<>();lru.offer(1);lru.offer(2);lru.offer(3);lru.offer(4);lru.offer(5);System.out.println(lru);lru.offer(6);lru.offer(7);lru.offer(8);lru.offer(9);System.out.println(lru);}
}

執行結果

5 4 3 2 
9 8 7 6 

首先將數字1到5依次加入緩存,當緩存容量達到上限4時,數字1被替換出去,然后繼續添加數字6到9,此時數字5被替換出去,最終緩存中只剩下數字6到9。

3. 基于鏈表實現LRU算法

import java.util.HashMap;
import java.util.Map;/*** 基于單鏈表實現LRU算法* @param <T>*/
public class LRUBaseLinkedList<T> {// 默認鏈表容量private final static int DEFAULT_CAPACITY = 5;// 頭節點private Node<T> head;// 鏈表長度private int size;// 鏈表容量private int capacity;// 記錄節點的前一個節點,方便刪除操作private Map<T, Node<T>> prevNodeMap;public LRUBaseLinkedList() {this(DEFAULT_CAPACITY);}public LRUBaseLinkedList(int capacity) {this.capacity = capacity;this.size = 0;this.head = new Node<>();this.prevNodeMap = new HashMap<>();}/*** 插入元素** @param data 待插入的元素*/public void add(T data) {if (data == null) {throw new IllegalArgumentException("Data cannot be null");}Node<T> prevNode = prevNodeMap.get(data);if (prevNode != null) {deleteElem(prevNode);} else {if (size >= capacity) {deleteLastElem();}}insertElemAtHead(data);}// 刪除尾節點private void deleteLastElem() {Node<T> ptr = head;while (ptr.next.next != null) {ptr = ptr.next;}prevNodeMap.remove(ptr.next.data);ptr.next = null;size--;}// 刪除當前節點的下一個節點private void deleteElem(Node<T> prevNode) {Node<T> temp = prevNode.next;prevNode.next = temp.next;prevNodeMap.remove(temp.data);temp = null;size--;}// 插入元素到鏈表頭節點private void insertElemAtHead(T data) {Node<T> next = head.next;head.next = new Node<>(data, next);prevNodeMap.put(data, head);size++;}// 定義內部存儲結構private static class Node<T> {T data;Node<T> next;Node() {}Node(T data, Node<T> next) {this.data = data;this.next = next;}}@Overridepublic String toString() {StringBuilder sb = new StringBuilder();Node<T> temp = head.next;while (temp != null) {sb.append(temp.data).append(" ");temp = temp.next;}return sb.toString();}public static void main(String[] args) {LRUBaseLinkedList<Integer> list = new LRUBaseLinkedList<>();list.add(1);list.add(2);list.add(3);list.add(4);list.add(5);System.out.println(list);list.add(6);System.out.println(list);list.add(4);System.out.println(list);}
}

執行結果

1 2 3 4 5 
6 1 2 3 4 
4 6 1 2 

在第一次插入元素時,鏈表中依次添加了1、2、3、4、5這五個元素,并打印了鏈表中的所有元素。
在第二次插入元素時,由于容量已滿,因此刪除了鏈表的尾部元素5,然后將新的元素6插入到了鏈表頭部。
在第三次插入元素時,元素4已經存在于鏈表中,因此刪除了元素4所在的位置,并將其移動到了鏈表頭部。

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

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

相關文章

董兆祥出席工業廢水資源化,開創變廢為寶新途徑演講

演講嘉賓&#xff1a;董兆祥 董事長 河北奧博水處理有限公司 演講題目&#xff1a;工業廢水資源化&#xff0c;開創變廢為寶新途徑 會議簡介 “十四五”規劃中提出&#xff0c;提高工業、能源領城智能化與信息化融合&#xff0c;明確“低碳經濟”新的戰略目標&#xff0c;熱…

springcloud:3.2測試超時機制

服務提供者 Openfeign遠程調用服務提供者搭建 文章地址http://t.csdnimg.cn/06iz8 PaymentController【控制層】 /*** 測試超時機制** return*/GetMapping("/timeout")public String TimeOut() {try {TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {…

應用層DDoS防護:理解、必要性與實現策略

一、應用層簡介 應用層&#xff0c;也稱作第七層&#xff0c;是OSI&#xff08;開放系統互聯&#xff09;模型中的最高層。在這一層&#xff0c;數據以特定的應用程序協議格式進行傳輸&#xff0c;如HTTP、FTP、SMTP等。應用層的主要職責是為用戶提供網絡服務&#xff0c;如文…

【筆記】Android Telephony 獲取SubscriptionManager和TelephonyManager

背景 早期的手機只有單卡 &#xff0c;基本用默認卡&#xff08;代碼如下&#xff09;&#xff0c;那么雙卡手機的業務邏輯就會存在問題。 //手動搜網的功能案例&#xff0c;根據卡槽/Phone對象直接獲取信息private Context mcontext context; private Phone mPhone PhoneF…

LeetCode 560. 和為 K 的子數組

由于題目要求子數組必須連續&#xff0c;也就是需要一個和為K的區間&#xff0c;可以利用前綴和預處理后&#xff0c;枚舉找到這些區間段[l,r]&#xff0c;使之滿足s[r] - s[l] k。 不理解前綴和的可以先看這里。 class Solution { public:int subarraySum(vector<int>…

MongoDB聚合運算符:$count

文章目錄 語法使用舉例在$group階段中使用在$setWindowFields階段使用 $count聚合運算符返回分組中文檔的數量。從5.0開始支持。 語法 { $count: { } }$count不需要參數 使用 $count可以用于下列聚合階段&#xff1a; $bucket$bucket$group$setWindowFields 在$group階段中…

【vuex之五大核心概念】

vuex:五大核心概念 一、state狀態1.state的含義2.如何訪問以及使用倉庫的數據&#xff08;1&#xff09;通過store直接訪問獲取store對象 &#xff08;2&#xff09;通過輔助函數MapState 二、mutations1.作用2.嚴格模式3.操作流程定義 mutations 對象&#xff0c;對象中存放修…

Freesia 項目引用的依賴

UML圖 項目總依賴 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.0</version> </parent> <groupId>com.freesia</groupId> <artifa…

計算機網絡_2.1 物理層概述

2.1 物理層概述 一、物理層要實現的功能二、物理層接口特性 B站 深入淺出計算機網絡 2.1物理層概述 一、物理層要實現的功能 物理層要實現的功能就是在各種傳輸媒體上傳輸比特0和1&#xff0c;進而給上面的數據鏈路層提供透明傳輸比特流的服務。 數據鏈路層“看不見”&#xff…

劍指offer面試題22:鏈表中倒數第k個節點

面試題22&#xff1a;鏈表中倒數第k個節點 題目&#xff1a; 實現一種算法&#xff0c;找出單向鏈表中倒數第 k 個節點。返回該節點的值。 示例&#xff1a; 輸入&#xff1a; 1->2->3->4->5 和 k 2 輸出&#xff1a; 4思路&#xff1a; 1、求倒數第k個節點的…

設計模式-命令模式(Command Pattern)

承接Qt/C軟件開發項目&#xff0c;高質量交付&#xff0c;靈活溝通&#xff0c;長期維護支持。需求所尋&#xff0c;技術正適&#xff0c;共創完美&#xff0c;歡迎私信聯系&#xff01; 一、命令模式的說明 命令模式&#xff08;Command Pattern&#xff09;是一種行為設計模式…

跨境代購系統獨立站:掌握核心競爭優勢,打造專業國際購物體驗

跨境代購系統獨立站&#xff08;獲取代購系統獨立站演示&#xff09;的核心競爭優勢可能包括&#xff1a; 獨立性&#xff1a;獨立站不依賴于任何第三方電商平臺&#xff0c;擁有自己的域名和網站空間&#xff0c;可以自主控制網站的設計和內容。靈活性&#xff1a;獨立站不受…

springboot基于web的網上攝影工作室的開發與實現論文

網上攝影工作室 摘要 隨著信息技術在管理上越來越深入而廣泛的應用&#xff0c;管理信息系統的實施在技術上已逐步成熟。本文介紹了網上攝影工作室的開發全過程。通過分析網上攝影工作室管理的不足&#xff0c;創建了一個計算機管理網上攝影工作室的方案。文章介紹了網上攝影工…

微信小程序云開發教程——墨刀原型工具入門(動態組件)

引言 作為一個小白&#xff0c;小北要怎么在短時間內快速學會微信小程序原型設計&#xff1f; “時間緊&#xff0c;任務重”&#xff0c;這意味著學習時必須把握微信小程序原型設計中的重點、難點&#xff0c;而非面面俱到。 要在短時間內理解、掌握一個工具的使用&#xf…

0基礎跨考計算機|408保姆級全年計劃

我也是零基礎備考408&#xff01; 雖說是計算機專業&#xff0c;但是本科一學期學十幾門,真的期末考試完腦子里什么都不進的...基本都是考前一周發瘋學完水過考試...&#x1f605; 想要零基礎跨考可以直接從王道開始&#xff01;跟教材一點一點啃完全沒必要&#x1f978; 現在…

八股文打卡day25——數據庫(2)

面試題&#xff1a;講一下事務的四大特性&#xff1f; 我的回答&#xff1a; ACID A代表原子性&#xff0c;一個事務代表一個業務&#xff0c;要么全部都完成&#xff0c;要么全部都不完成。如果事務執行失敗了&#xff0c;會回滾到最原來的狀態。 C代表一致性&#xff0c;舉…

【STM32】江科大STM32學習筆記匯總(50)

00. 目錄 文章目錄 00. 目錄01. STM32學習筆記匯總02. 相關資料下載03. 附錄 01. STM32學習筆記匯總 【STM32】STM32學習筆記-課程簡介(01) 【STM32】STM32學習筆記-STM32簡介(02) 【STM32】STM32學習筆記-軟件安裝(03) 【STM32】STM32學習筆記-新建工程(04) 【STM32】STM…

venv、pip、conda、anaconda、miniconda的區別和優缺點,和徹底清除python多余的環境

virtualenv(venv) 這是一個虛擬環境管理器&#xff0c;它可以讓你每個項目甚至每個腳本配置一個自定義的Python解釋器環境&#xff0c;這最大的好處是我可以不污染開發環境。? pip pip 是 Python 最常用的包管理器&#xff0c;它能自動處理依賴 。 conda 如果說venv是虛擬…

CSS特性

小技巧&#xff1a;在調試工具中&#xff0c;css樣式上看層疊&#xff0c;下看繼承。 1、層疊性 相同的屬性會被覆蓋&#xff0c;不同的屬性會疊加 2、繼承性 3、優先級 基于不同種類的選擇器的匹配規則。 通配符 < 標簽 < 類選擇器 < id選擇器 < 行內樣式 <…

大語言模型(LLM)技術名詞表(一)

LLMs on a Phone&#xff1a;指在手機設備上運行的大型語言模型。 Scalable Personal AI&#xff1a;指用戶可以在個人設備上對AI模型進行微調的技術。 Responsible Release&#xff1a;發布AI模型時考慮社會、法律和倫理影響的做法。 Multimodality&#xff1a;AI模型能處理…