LRU与LFU

作者: 小幸运Q | 来源:发表于2021-03-21 22:40 被阅读0次

LRU

  • 注意 map<int,list<pair<int,int>>::iterator>m; 要加iterator要不然没法指向List内元素。还有list<pair<int,int>>List;

  • LRU注意添加元素时要检查溢出时是否已有该元素,如果有则先get更新,再修改队首该元素的second值。

class LRUCache {
public:
    list<pair<int,int>>List;
    map<int,list<pair<int,int>>::iterator>m;
    int maxlength=0;
    LRUCache(int capacity) {
        maxlength=capacity;
    }
    
    int get(int key) {
        // 如果有该元素删除map对应的位置,再插入freq++的位置末尾
        if(m.count(key)==1){
            int second=m[key]->second;
            List.erase(m[key]);
            m.erase(key);
            List.push_back(make_pair(key,second));
            m[key]=--List.end();
            return second;
        }
        else{
            return -1;
        }
    }
    
    void put(int key, int value) {
        // 如果存在该元素则get更新,否则就当没操作过
        get(key);
        if(m.count(key)==1){
            m[key]->second=value;
            return ;
        }
        if(maxlength==m.size()){
            m.erase(List.begin()->first);
            List.erase(List.begin());
        }
        List.push_back(make_pair(key,value));
        m[key]=--List.end();
    }
};

LFU

LFU的push遇到重复元素不删除key,只是get更新key之后对value进行覆盖。

map<int,pair<int,list<pair<int,int>>::iterator>>KeyFreq用iterator指向FreqList的List中的一个节点。

class LFUCache {
public:
    int length;
    map<int,list<pair<int,int>>>FreqList;
    map<int,pair<int,list<pair<int,int>>::iterator>>KeyFreq;
    int minFreq;
    LFUCache(int capacity) {
        length=capacity;
        minFreq=0;
    }
    
    int get(int key) {
        if(length<=0||KeyFreq.count(key)==0){
            return -1;
        }
        auto l=KeyFreq[key].second;
        int freq=KeyFreq[key].first;
        int value=l->second;
    
        FreqList[freq].erase(l);
        if(freq==minFreq&&FreqList[freq].size()==0){
            minFreq=freq+1;
        }
        FreqList[freq+1].push_front(make_pair(key,value));
        KeyFreq[key]=make_pair(freq+1,FreqList[freq+1].begin());
        return value;
    }
    
    void put(int key, int value) {
        if(length<=0){
            return;
        }
        if(KeyFreq.count(key)==1){
            // 内部原有元素
            get(key);
            auto l=KeyFreq[key].second;
            l->second=value;
        }
        else{
            if(length==KeyFreq.size()){
                // 遇到push溢出的情况
                auto l=(--FreqList[minFreq].end());
                int key=l->first;
                FreqList[minFreq].erase(l);
                KeyFreq.erase(key);
            }            
            FreqList[0].push_front(make_pair(key,value));
            KeyFreq[key]=make_pair(0,FreqList[0].begin());
            minFreq=0;
        }
    }
};
  • 优势:

在数据访问符合正态分布时,相比于LRU算法,LFU算法的缓存命中率会高一些。

  • 劣势:

(1)LFU的复杂度要比LRU更高一些。
(2)需要维护数据的访问频次,每次访问都需要更新。
(3)早期的数据相比于后期的数据更容易被缓存下来,导致后期的数据很难被缓存。
(4)新加入缓存的数据很容易被剔除,像是缓存的末端发生“抖动”。

相关文章

  • Algorithm进阶计划 -- LRU 与 LFU 算法

    LRU 与 LFU 算法LRU 算法LFU 算法 1. LRU 算法 LRU 算法是一种缓存淘汰策略,是 Leas...

  • LRU与LFU

    LRU 注意 map >::iterator>m; 要加iterator要不然没法指向List内元素。还有list...

  • groupcache 源码系列三 LRU

    关于LRU,可以参考LRU LFU FIFO LRU全称是Least Recently Used,即最近最久未使用...

  • LRU和LFU的CPP实现

    LRU(least recently used cache) LFU(least frequently used ...

  • [LeetCode] LRU和LFU详解之一

    LRU (Least recently used,最近最少使用 ) 和 LFU (Least frequently...

  • LFU

    LFU:least frequently used最不经常使用 LFU比LRU难一点,加入了使用量的概念,需要维护...

  • LRU 和 LFU 缓存淘汰算法

    缓存淘汰算法有很多种,这里只简单介绍2种:LRU 和 LFU。 LRU全称 Least recently used...

  • LRU与LFU缓存算法

    一、背景 缓存算法也是也是我们日常使用的操作系统、应用程序内部用得比较多的一种调度算法,之前也是了解个过程没具体实...

  • LRU LFU FIFO

    一、LRU LRU全称是Least Recently Used,即最近最久未使用的意思。如果一个数据在最近一段时间...

  • LRU & LFU

    1.LFU 1.1.原理 LFU(LeastFrequentlyUsed)算法根据数据的历史访问频率来淘汰数据,其...

网友评论

      本文标题:LRU与LFU

      本文链接:https://www.haomeiwen.com/subject/pcvwcltx.html