golang 实现Lru

golang LRU

package main

type Node struct {
    Key,Value int
    //双链表
    Pre,Next *Node
}


type LruCache struct {
    //现有元素数量
    Size int
    //lru容量
    Capacity int
    //map存储链表节点,查询速度O(1)
    HashMap map[int]*Node
    //哨兵头尾,方便节点插入初始位置
    Dummy,Tail *Node
}

//初始化新节点
func InitNode(key,value int)*Node  {
    return &Node{
        Key: key,
        Value: value,
    }
}

//初始化Lru
func (m*LruCache)InitLruCache(capacity int)LruCache  {
    l:=LruCache{
        Capacity: capacity,
        HashMap: make(map[int]*Node,capacity),
        Dummy: InitNode(0,0),
        Tail: InitNode(0,0),
    }
    //头尾连接
    l.Dummy.Next=l.Tail
    l.Tail.Pre = l.Dummy
    return l
}

//两个基础函数,增加到头,移除节点,方便使用

//增加到头部
func (m*LruCache)AddToHead(n*Node)  {
    //双向链表,两边都增加
    n.Next = m.Dummy.Next
    n.Pre = m.Dummy
    m.Dummy.Next.Pre = n
    m.Dummy.Next = n
}

//移除节点
func (m*LruCache)Remove(n*Node)  {
    n.Pre.Next = n.Next
    n.Next.Pre = n.Pre
}


//节点移动,删除节点,移动到头部
func (m*LruCache)MoveHead(n*Node)  {
    m.MoveHead(n)
    m.AddToHead(n)
}


//超过容量,删除最后一个
//其实是删除tail的pre,返回node,方便移除map中的数据
func (m*LruCache)DelTail()*Node  {
    n:=m.Tail.Pre
    m.Remove(n)
    return n
}

//主要的get和put函数

//get    key获取value 没有返回-1
func (m*LruCache)Get(key int)int {
    if _,ok :=m.HashMap[key];!ok{
        return -1
    }
    //使用到,移到头,返回value
    n:=m.HashMap[key]
    m.MoveHead(n)
    return n.Value
}

//put  存在直接改值,不存在,加入判断是否超出长度,超出删尾部
func (m*LruCache)Put(key,value int) {
    if _,ok:=m.HashMap[key];ok{
        n:=m.HashMap[key]
        n.Value = value
        m.MoveHead(n)
    }else{
        if m.Size+1>m.Capacity{
            node:=m.DelTail()
            //上面是移除链表,记得移除map中的数据
            delete(m.HashMap,node.Key)
            m.Size--
        }
        n:=InitNode(key,value)
        m.HashMap[key] = n
        //map添加元素,但是链表未增加节点,所以调用AddToHead,添加节点到链表即可,不要使用MoveHead
        m.AddToHead(n)
        m.Size++
    }
}

LFU c++

实现方式有很多

struct Node{
    int key;
    int value;
    int freq;
    Node(int k,int v,int f):key(k),value(v),freq(f){}
};

class LFUCache {
public:
    int cap,minFreq;
    unordered_map<int,list<Node>::iterator>keys;
    unordered_map<int,list<Node>>freqs;
    LFUCache(int capacity) {
        cap = capacity;
        minFreq = 0;
        keys.clear();
        freqs.clear();
    }
    
    int get(int key) {
        if(cap==0)return -1;
        auto it = keys.find(key);
        if(it==keys.end())return -1;
        //正常流程
        list<Node>::iterator p = it->second;
        int value = p->value,fre = p->freq;
        freqs[fre].erase(p);//去除迭代器
        if(freqs[fre].size()==0)
        {
            freqs.erase(fre);
            if(fre==minFreq)minFreq++;
        }
        //增加新的
        freqs[fre+1].push_front(Node(key,value,fre+1));
        keys[key] = freqs[fre+1].begin();//放的是迭代器
        return value; 
    }
    
    void put(int key, int value) {
        if(cap==0)return;
        //存在,不存在
        auto it = keys.find(key);
        if(it==keys.end())
        {
            if(keys.size()==cap)
            {
               auto p =freqs[minFreq].back();//最小的尾部
               keys.erase(p.key);
               freqs[minFreq].pop_back();
               if(freqs[minFreq].size()==0)//移除后最小没了,去除此节点
               {
                   freqs.erase(minFreq);
               }
            }
            //容量判断之后
             freqs[1].push_front(Node(key,value,1));
               keys[key] = freqs[1].begin();//key放迭代器?
               minFreq = 1;
        }else{
            //存在
            list<Node>::iterator p = it->second;//获取迭代器
            int fre = p->freq;
            freqs[fre].erase(p);//删除需要迭代器
            if(freqs[fre].size()==0)
            {
                 freqs.erase(fre);
                 if(fre==minFreq)minFreq++;
            }
            freqs[fre+1].push_front(Node(key,value,fre+1));
            keys[key] = freqs[fre+1].begin();
        }
    }
};

/**
 * Your LFUCache object will be instantiated and called as such:
 * LFUCache* obj = new LFUCache(capacity);
 * int param_1 = obj->get(key);
 * obj->put(key,value);
 */

posted @ 2021-01-05 11:26  海拉尔  阅读(455)  评论(0编辑  收藏  举报