【数据结构实践】LRU缓存策略模拟

题目来自lintcode134

为最近最少使用(Least Recently UsedLRU)缓存策略设计一个数据结构,它应该支

持以下操作:获取数据和写入数据。

² get(key) 获取数据:如果缓存中存在 key,则获取其数据值(通常是正数),否则返回

-1。

² set(key, value) 写入数据:如果 key 还没有在缓存中,则写入其数据值。当缓存达到上

限,它应该在写入新数据之前删除最近最少使用的数据用来腾出空闲位置。

最终, 你需要返回每次 get 的数据。

整体上最大的难点就是无法用同一个数据结构完成查找和顺序的组织两大核心功能,既然如此,就使用两个数据结构完成,利用哈希查找的优势,辅以逻辑增删(物理删除是浪费时间的很大一个部分),加上使用双向链表便捷地操作元素的顺序,给出最远未使用的元素,整体上极大地加快了速度,当然代码行数也增加了一倍。

教训:

  1. LRU删除时删除的时最远未使用的,和最少没关系,题目表述有问题。
  2. 欲利用哈希查找快的优点,就要接受其无序或者说组织顺序比较困难的缺点,而欲利用链表顺序组织方便快捷的优点,就要接收它难以查找的缺点,程序员做的事情就是综合长处,精巧
#include<iostream>
#include<unordered_map>
using namespace std;
struct group {
    int val;
    int key;
    group* leftlink;
    group* rightlink;
    group(int value, int k_) {
        val = value;
        key = k_;
        leftlink = nullptr;
        rightlink = nullptr;
    }
};

class LRUCache {
private:
    group* use_head;
    group* use_tail;
    unordered_map<int, pair<bool, group*>> useage;
    int upline;
    int now;
public:
    /*
    * @param capacity: An integer
    */LRUCache(int capacity) {
        upline = capacity;
        now = 0;
        use_head = nullptr;
        use_tail = nullptr;
    }

    /*
     * @param key: An integer
     * @return: An integer
     */
    int get(int key) {
        if (useage.find(key) == useage.end() || useage.find(key)->second.first == false) {
            return -1;
        }
        else {
            group* temp = useage.find(key)->second.second;
            if (temp->leftlink==nullptr&&temp->rightlink!=nullptr ) {
                temp->rightlink->leftlink = nullptr;
                use_head = temp->rightlink;
                temp->leftlink = use_tail;
                temp->rightlink = nullptr;
                use_tail->rightlink = temp;
                use_tail = temp;
            }
            else if (temp == use_tail||(temp->leftlink==nullptr&&temp->rightlink==nullptr)) {

            }
            else {
                temp->leftlink->rightlink = temp->rightlink;
                temp->rightlink->leftlink = temp->leftlink;
                temp->leftlink = use_tail;
                temp->rightlink = nullptr;
                use_tail->rightlink = temp;
                use_tail = temp;
            }
            return use_tail->val;
        }
    }

    /*
     * @param key: An integer
     * @param value: An integer
     * @return: nothing
     */
    void set(int key, int value){
        if (useage.find(key) == useage.end() || useage.find(key)->second.first == false) {
            if (now < upline)
            {
                //connect temp with tail node drictly
                group* temp = new group(value, key);
                //if linklist is empty , the first is head and tail
                if (use_head == nullptr) {
                    use_head = temp;
                    use_tail = temp;
                }
                else {
                    use_tail->rightlink = temp;
                    temp->leftlink = use_tail;
                    use_tail = temp;
                }
                if (useage.find(key)== useage.end()) {
                    useage.insert({ key,{ true,temp } });
                }
                else {
                    useage.find(key)->second.first = true;
                }
                now++;
            }
            else {
                //delete first node
                useage.find(use_head->key)->second.first = false;
                if (use_head->rightlink == nullptr){
                    delete use_head;
                    use_head = nullptr;
                }
                else {
                    use_head = use_head->rightlink;
                    delete use_head->leftlink;
                    use_head->leftlink = nullptr;
                }
                //connect temp with tail node
                group* temp = new group(value, key);
                use_tail->rightlink = temp;
                temp->leftlink = use_tail;
                use_tail = temp;
                if (useage.find(key) == useage.end()) {
                    useage.insert({ key,{ true,temp } });
                }
                else {
                    useage.find(key)->second.first = true;
                    useage.find(key)->second.second = use_tail;
                }
            }
        }
        else {
            useage.find(key)->second.second->val = value;


            //ensure this node at the tail of whole linklist
            group* temp = useage.find(key)->second.second;
            if (temp != use_tail&&temp!=use_head) {
                temp->leftlink->rightlink = temp->rightlink;
                temp->rightlink->leftlink = temp->leftlink;
                temp->leftlink = use_tail;
                temp->rightlink = nullptr;
                use_tail->rightlink = temp;
                use_tail = temp;
            }
            else if (temp == use_head&&temp!= use_tail) {             
                    temp->rightlink->leftlink = nullptr;
                    use_head = temp->rightlink;
                    temp->leftlink = use_tail;
                    temp->rightlink = nullptr;
                    use_tail->rightlink = temp;
                    use_tail = temp;
            }
        }
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值