LRU算法实现

最近最少使用算法,主要思路:
双链表:双链表存储数据,插入和删除元素都很方便,复杂度都是O(1)。
头节点是最近使用的元素,尾节点是最近最少使用,即需要淘汰的节点。
空间满了的话,就淘汰尾节点,新增元素时,放在头节点。
在读写操作时,如果命中缓存,就把该节点从当前位置移植到头节点

为什么不用数组,因为插入和删除需要平移元素,复杂度是O(n)。

哈希map:
用于查找数据,key是数据的key,value是数据的指针(即数据在双链表中的位置)

最大容量:
如果超过容量,就把尾节点淘汰,新数据添加到头节点。


Java实现

java中双链表用LinkedList数据结构,底层用双链表实现。

class LRUCache {

    public class Node {
        int key;
        int value;
        Node(int key, int value) {
            this.key = key;
            this.value = value;
        }
    }

    /**
     * map用于存储key对应的节点
     */
    private Map<Integer, Node> map = new HashMap<>();
    /**
     * 双链表存储,头节点是最近使用的元素,尾节点是最近最少使用
     * 空间满了的话,就淘汰尾节点
     * 新增元素时,放在头节点
     */
    private LinkedList<Node> dList = new LinkedList<>();
    private int MAX_SIZE;
    public LRUCache(int capacity) {
        MAX_SIZE = capacity;
    }

    /**
     * 如果关键字 key 存在于缓存中,则返回关键字的value,否则返回 -1
     * @param key
     * @return
     */
    public int get(int key) {
        if (map.containsKey(key)) {
            Node data = map.get(key);
            dList.remove(data);
            dList.addFirst(data);
            return data.value;
        }
        return -1;
    }

    /**
     * 如果关键字 key 已经存在,则变更其数据值 value ;
     * 如果不存在,则向缓存中插入该组 key-value 。
     * 如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字(即尾节点)
     * 新数据插入头节点
     * @param key
     * @param value
     */
    public void put(int key, int value) {
        if (map.containsKey(key)) {
            Node cache = map.get(key);
            cache.value = value;
            dList.remove(cache);
            dList.addFirst(cache);
            return;
        }
        if (dList.size()+1 > MAX_SIZE) {
            Node cache = dList.removeLast();
            map.remove(cache.key);
        }
        Node data = new Node(key, value);
        dList.addFirst(data);
        map.put(key, data);
    }
}

C++实现

std::list是双链表

unordered_map用于查找

struct Node {
    int key;
    int value;
    Node(int key, int value) {
        this->key = key;
        this->value = value;
    }
};

class LRUCache {
public:
    int _MAX_SIZE;
    std::list<Node*> _dlist;
    std::unordered_map<int, std::list<Node*>::iterator> _dmap;
    
    LRUCache(int size) {
        this->_MAX_SIZE =  size;       
    }

    int get(int key) {
        auto it = _dmap.find(key);
        if (it != _dmap.end()) {
            Node* data = move2Front(it->second);
            return data->value;
        }
        return -1;
    }

    void put(int key, int value) {
        auto it = _dmap.find(key);
        if (it != _dmap.end()) {
            Node* data = move2Front(it->second);
            data->value = value;
            return;
        }
        Node* newData = new Node(key, value);
        if (_dlist.size() + 1 > _MAX_SIZE) {
            Node* deleteNode = _dlist.back();
            _dmap.erase(deleteNode->key);
            _dlist.pop_back();
            delete deleteNode;
        }
        _dlist.push_front(newData);
        _dmap[key] = _dlist.begin();
    }

    Node* move2Front(std::list<Node*>::iterator it) {
        Node* data = *it;
        _dlist.erase(it);
        _dlist.push_front(data);
        _dmap[data->key] = _dlist.begin();
        return data;
    }   
};

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值