[TypeScript]手擼LFU

[TypeScript]手擼LFU

最近做筆試的時候遇到了要手擼LFU的題目,LFU在vue源碼里還是有使用的,例如keep-alive的實現機制就是基于它來搞的。不多說了,直接上代碼。

代碼

// 雙向鏈表node
class DoubleLinkNode {key: number;val: number;freq: number;prev?: DoubleLinkNode | null;next?: DoubleLinkNode | null;constructor(key, val, freq) {this.freq = freq;this.key = key;this.val = val;}
}// 雙向鏈表
class DoubleLink {size: number;head: DoubleLinkNode | null;tail: DoubleLinkNode | null;constructor() {this.size = 0;this.head = null;this.tail = null;}// 刪除一個節點remove(node: DoubleLinkNode) {// 空鏈表if (this.size < 1) {return;}// 只有一個元素if (this.size === 1) {this.size = 0;this.head = null;this.tail = null;return;}// 刪的是頭結點if (node === this.head) {const nextNode = node.next;nextNode.prev = null;this.head = nextNode;this.size--;return;}// 刪的是尾結點if (node === this.tail) {const prevNode = node.prev;prevNode.next = null;this.tail = prevNode;this.size--;return;}// 正常刪中間節點const prevNode = node.prev;const nextNode = node.next;prevNode.next = nextNode;nextNode.prev = prevNode;this.size--;}// 在尾部插入一個節點addLast(node: DoubleLinkNode) {// 空鏈表if (this.size === 0) {this.head = node;this.tail = node;} else {// 非空鏈表const curTail = this.tail;curTail.next = node;node.prev = curTail;this.tail = node;}this.size++;}// 是否是空鏈表isEmpty() {return this.size === 0;}
}// 實現LFU緩存
class LFUCache {keyToNodeMap: Map<number, DoubleLinkNode>;freqToKeysMap: Map<number, DoubleLink>;capacity: number;minFreq: number;constructor(capacity: number) {this.keyToNodeMap = new Map();this.freqToKeysMap = new Map();this.capacity = capacity;this.minFreq = 0;}get(key: number): number {if (!this.keyToNodeMap.has(key)) {return -1;}const node = this.keyToNodeMap.get(key);// 增加頻次this.increaseFreq(node);return node.val;}put(key: number, value: number): void {// key已經存在if (this.keyToNodeMap.has(key)) {// 修改對應的node的val即可const node = this.keyToNodeMap.get(key);node.val = value;this.increaseFreq(node);} else {// key不存在// 容量滿了if (this.keyToNodeMap.size >= this.capacity) {// 刪除最小頻次中最久沒使用的this.removeMinFreqKey();}// ------------正式開始插入------------const newNode = new DoubleLinkNode(key, value, 1);this.keyToNodeMap.set(key, newNode);if (!this.freqToKeysMap.get(1)) {this.freqToKeysMap.set(1, new DoubleLink());}// 維護頻次表const link = this.freqToKeysMap.get(1);link.addLast(newNode);// 插入新 key 后最小的 freq 肯定是 1this.minFreq = 1;}}// 增加頻次increaseFreq(node: DoubleLinkNode) {const oldFreq = node.freq;const newFreq = node.freq + 1;node.freq = newFreq;// 維護頻次表const oldFreqLink = this.freqToKeysMap.get(oldFreq);// 從舊頻次表中刪除這個nodeoldFreqLink.remove(node);if (oldFreqLink.isEmpty()) {this.freqToKeysMap.delete(oldFreq);// 如果這個頻次正好是最低頻次,記得更新最小頻次if (this.minFreq === oldFreq) {this.minFreq = newFreq;}}// 維護新頻次表if (!this.freqToKeysMap.get(newFreq)) {this.freqToKeysMap.set(newFreq, new DoubleLink());}const newFreqLink = this.freqToKeysMap.get(newFreq);newFreqLink.addLast(node);}// 刪除最小頻次中最久沒使用的removeMinFreqKey() {const minFreqLink = this.freqToKeysMap.get(this.minFreq);// 其中最先被插入的那個 node 就是該被淘汰的 nodeconst deletedNode = minFreqLink.head;// 維護最小頻次mapminFreqLink.remove(deletedNode);if (minFreqLink.isEmpty()) {this.freqToKeysMap.delete(this.minFreq);}// key表中刪除對應Nodethis.keyToNodeMap.delete(deletedNode.key);}// log調試方法print() {console.log('keyToNodeMap: ', this.keyToNodeMap);console.log('freqToKeysMap: ', this.freqToKeysMap);}
}

思路

LFU(Least Frequently Used)緩存是一種緩存淘汰策略,它根據元素的使用頻率來決定哪些元素應該被淘汰。在你提供的代碼中,LFUCache 類實現了這種策略,下面是它的工作原理的詳細描述:

  1. 數據結構

    • DoubleLinkNode:表示雙向鏈表中的節點,包含鍵(key)、值(val)和頻率(freq)。
    • DoubleLink:表示雙向鏈表,包含頭尾節點以及鏈表的大小。
    • MapkeyToNodeMap 用于存儲鍵到節點的映射,freqToKeysMap 用于存儲頻率到鍵的映射。
  2. 構造函數

    • 初始化 LFUCache 時,設置緩存的容量(capacity),并初始化鍵到節點的映射和頻率到鍵的映射。
  3. get 方法

    • 檢查鍵是否存在于 keyToNodeMap 中。
    • 如果存在,找到對應的節點,并調用 increaseFreq 方法來增加節點的使用頻率。
    • 返回節點的值。
  4. put 方法

    • 檢查鍵是否已存在:
      • 如果存在,更新節點的值,并增加頻率。
      • 如果不存在,并且緩存已滿,則調用 removeMinFreqKey 方法來刪除最小頻率的鍵。
    • 創建新節點,并將其添加到 keyToNodeMapfreqToKeysMap 中。
  5. increaseFreq 方法

    • 增加節點的使用頻率。
    • 從舊頻率的鏈表中刪除節點,并檢查是否需要更新最小頻率。
    • 將節點添加到新頻率的鏈表中。
  6. removeMinFreqKey 方法

    • 找到最小頻率鏈表的頭節點,即最久未使用的節點。
    • 從鏈表中刪除該節點,并更新 freqToKeysMap
    • keyToNodeMap 中刪除對應的鍵。
  7. print 方法

    • 用于調試,打印當前的鍵到節點映射和頻率到鍵的映射。

這種實現方式確保了:

  • 每個鍵的使用頻率都被跟蹤。
  • 當緩存達到容量限制時,最少使用頻率的鍵將被淘汰。
  • 通過雙向鏈表,可以快速地添加和刪除節點,同時保持鏈表的順序。

這種緩存策略適用于那些需要平衡訪問頻率和最近使用情況的場景。

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

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

相關文章

阿一課代表今日分享之使用dnscat2 進行dns隧道反彈shell(直連模式linux對linux)

DNS介紹 DNS是域名系統(Domain Name System)的縮寫&#xff0c;是因特網的一項核心服務&#xff0c;它作為可以將域名和IP地址相互映射的一個分布式數據庫&#xff0c;能夠使人更方便的訪問互聯網&#xff0c;而不用去記住能夠被機器直接讀取的IP數串。 DNS的記錄類型有很多&a…

歸并排序算法Python實現

歸并排序原理和步驟 1. 將數組分成兩半&#xff0c;直到每個子數組的長度為1 首先&#xff0c;將數組分成兩半。如果數組的長度大于1&#xff0c;將其從中間分割為兩個子數組。對每個子數組繼續進行這個過程&#xff0c;直到每個子數組的長度為1。此時&#xff0c;所有子數組…

L4 Persistence and Streaming

參考自https://www.deeplearning.ai/short-courses/ai-agents-in-langgraph&#xff0c;以下為代碼的實現。 這里主要是加入了memory&#xff0c;這樣通過self.graph graph.compile(checkpointercheckpointer)就可以加入持久性的檢查點通過thread {"configurable"…

項目實戰--Spring Boot + GraphQL實現實時數據推送

背景 用戶體驗不斷提升而3對實時數據的需求日益增長&#xff0c;傳統的數據獲取方式無法滿足實時數據的即時性和個性化需求。 GraphQL作為新興的API查詢語言&#xff0c;提供更加靈活、高效的數據獲取方案。結合Spring Boot作為后端框架&#xff0c;利用GraphQL實現實時數據推…

Java筆試|面試 —— 對多態性的理解

談談對多態性的理解&#xff1a; 一個事物的多種形態&#xff08;編譯和運行時狀態不一致性&#xff09; 實現機制&#xff1a;通過繼承、重寫和向上轉型&#xff08;Object obj new 子類()&#xff09;來實現。 1.廣義上的理解 子類對象的多態性&#xff0c;方法的重寫&am…

visual studio 2022 在使用open3d出現的問題及解決方式

當出現以下問題&#xff1a; 使用open3d::utility::LogInfo系列出現LNK2001問題&#xff0c;如下所示&#xff1a;LNK2001 無法解析的外部符號 “char __cdecl fmt::v6::internal::decimal_point_impl(class fmt::v6::internal::locale_ref)” LNK2001 無法解析的外部符號 “p…

【C/C++】SDKDDKVer.h和WinSDKVer.h詳解及二者區別

一.SDKDDKVer.h介紹 SDKDDKVer.h 是一個在 Windows 軟件開發中常見的頭文件&#xff0c;它用于定義軟件開發工具包&#xff08;SDK&#xff09;和驅動開發工具包&#xff08;DDK&#xff09;的版本信息。這個文件通常位于 Visual Studio 安裝目錄下的 Include 子目錄中。 …

GD32MCU如何實現掉電數據保存?

大家在GD32 MCU應用時&#xff0c;是否會碰到以下應用需求&#xff1a;希望在MCU掉電時保存一定的數據或標志&#xff0c;用以記錄一些關鍵的數據。 以GD32E103為例&#xff0c;數據的存儲介質可以選擇內部Flash或者備份數據寄存器。 如下圖所示&#xff0c;片內Flash具有10年…

學習數據庫的增刪改查

一、創建數據庫和表 在進行增刪改查操作之前&#xff0c;我們需要創建一個數據庫和表。 1. 創建數據庫 使用 CREATE DATABASE 語句創建數據庫&#xff1a; CREATE DATABASE test_db;2. 選擇數據庫 使用 USE 語句選擇數據庫&#xff1a; USE test_db;3. 創建表 使用 CREA…

詳解C語言結構體

文章目錄 1.結構體的聲明1.1 結構體的基礎知識1.2 結構的聲明1.3 結構成員的類型 1.4結構體變量的定義和初始化2.結構體成員的訪問3.結構體傳參 1.結構體的聲明 1.1 結構體的基礎知識 結構是一些值的集合&#xff0c;這些值稱為成員變量。結構的每個成員可以是不同類型的變量 …

【密碼學】分組密碼概述

一、分組密碼的定義 分組密碼和流密碼都是對稱密碼體制。 流密碼&#xff1a;是將明文視為連續的比特流&#xff0c;對每個比特或字節進行實時加密&#xff0c;而不將其分割成固定的塊。流密碼適用于加密實時數據流&#xff0c;如網絡通信。分組密碼&#xff1a;是將明文數據…

【React】Ant Design -- Table分頁功能實現

實現步驟 為Table組件指定pagination屬性來展示分頁效果在分頁切換事件中獲取到篩選表單中選中的數據使用當前頁數據修改params參數依賴引起接口重新調用獲取最新數據 const pageChange (page) > {// 拿到當前頁參數 修改params 引起接口更新setParams({...params,page})…

翰德恩咨詢賦能材料行業上市公司,共筑IPD管理體系新篇章

賦能背景概覽 坐落于江蘇的某材料行業領軍企業&#xff0c;作為國內無機陶瓷膜元件及成套設備領域的佼佼者&#xff0c;以其龐大的生產規模、豐富的產品系列及卓越的研發實力&#xff0c;屹立行業之巔二十余年。公司不僅在新材料研發、技術創新、工藝設計、設備制造及整體解決…

【VUE進階】安裝使用Element Plus組件

Element Plus組件 安裝引入組件使用Layout 布局button按鈕行內表單菜單 安裝 包管理安裝 # 選擇一個你喜歡的包管理器# NPM $ npm install element-plus --save# Yarn $ yarn add element-plus# pnpm $ pnpm install element-plus瀏覽器直接引入 例如 <head><!-- I…

Transformer-LSTM預測 | Matlab實現Transformer-LSTM時間序列預測

Transformer-LSTM預測 | Matlab實現Transformer-LSTM時間序列預測 目錄 Transformer-LSTM預測 | Matlab實現Transformer-LSTM時間序列預測效果一覽基本介紹程序設計參考資料 效果一覽 基本介紹 1.Matlab實現Transformer-LSTM時間序列預測&#xff0c;Transformer-LSTM&#xf…

淺談“不要卷模型,要卷應用”

目錄 1.概述 2.AI技術應用場景探索 3.避免超級應用陷阱的策略 3.1.追求DAU的弊端 3.2.平衡用戶活躍度與應用實用性的策略 4.個性化智能體開發 4.1. 用戶需求分析與數據收集 4.2. 技術選擇與開發 4.3. 個性化算法設計 4.4. 安全性與隱私保護 4.5. 多渠道集成與響應機…

用vite創建Vue3項目的步驟和文件解釋

創建項目的原則是不能出現中文和特殊字符&#xff0c;最好為小寫字母&#xff0c;數字&#xff0c;下劃線組成 之后在visual studio code 中打開創建的這個項目 src是源代碼文件 vite和webpack是有去別的&#xff0c;對于這個vite創建的工程來說index.js是入口文件 在終端里面輸…

數字探秘:用神經網絡解密MNIST數據集中的數字!

用神經網絡解密MNIST數據集中的數字&#xff01; 一. 介紹1.1 MNIST數據集簡介1.2 MLP&#xff08;多層感知器&#xff09;模型介紹1.3 目標&#xff1a;使用MLP模型對MNIST數據集中的0-9數字進行分類 二.數據預處理2.1 數據集的獲取與加載2.2 數據集的探索性分析&#xff08;E…

騙子用出國月薪3萬騙了1000多萬上千名求職者被騙

日前,江蘇省南通市崇川區人民法院開庭審理了一起涉及詐騙的案件,該案件 審理后引發全國求職者的關注以及熱議。根據了解得知,這起案件的主犯是利用出 國勞務的虛假高薪職位位誘餌,最終有上千名求職者被騙上當了。文章來源于&#xff1a;股城網www.gucheng.com 根據法院審…

微信文件太大傳不了?學會這些,微信秒變大文件傳輸神器

在數字化時代&#xff0c;微信已成為我們日常溝通的重要橋梁。然而&#xff0c;當需要在微信上傳輸大文件時&#xff0c;文件大小的限制往往讓人束手無策。 今天&#xff0c;我們將分享一些實用的技巧&#xff0c;幫助你在微信上輕松傳輸大文件&#xff0c;無論是工作文檔還是…