zoukankan      html  css  js  c++  java
  • 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);
     */
    
    
  • 相关阅读:
    nginx配置404
    js修改浏览器url
    mysql DATE_ADD DATE_SUB
    centos6.5 ssh安全优化,修改默认端口名,禁止root远程登录
    关于mysql varchar 类型的最大长度限制
    IIS7多域名绑定同一物理目录,设置不同默认文档的解决方案
    获取某个数据所在数据列表中的行数 mysql
    安全模式不能删除使用SET SQL_SAFE_UPDATES = 0;
    Failed to run the WC DB work queue associated with 错误的解决
    mysql正则匹配解决查询一个字段是否在另一个字段中
  • 原文地址:https://www.cnblogs.com/9527s/p/14234757.html
Copyright © 2011-2022 走看看