leetcode146.LRU缓存机制

LRU,最近最少使用算法

 

//思路
//用哈希表,存key指向数据节点的指针
//双链表存数据节点,最前是最早使用,控制链表长度,通过哈希可以很快找到双链表中的指定的数据节点

// 定义一个双链表,数据节点,保存了数据
struct Node{
    int key,value;
    Node* prex;
    Node* next;
    Node():key(0),value(0),prex(nullptr),next(nullptr){}
    Node(int a, int b):key(a),value(b),prex(nullptr),next(nullptr){}
};



class LRUCache {

private:
    // 链表最大长度和当前容量,链表的头指针,尾指针, 哈希表
    int len;
    int n;
    unordered_map<int, Node*> hashmap;
    Node * head;
    Node * tail;

public:
    LRUCache(int capacity) {
        // 初始化指针,长度,头尾节点
        len = capacity;
        n = 0;
        head = new Node();
        tail = new Node();
        head->next= tail;
        tail->prex= head;
    }
    
    int get(int key) {
        //目标不在缓存,即不在链表中
        if(!hashmap.count(key))
            return -1;
        //在的情况下,返回数据,同时将节点放到链表头,表示最近使用了
        Node* oneptr = hashmap[key];
        MoveTohead(oneptr);
        return oneptr->value;
    }
    
    void put(int key, int value) {
        // 如果节点不存在,创建新的
        if(!hashmap.count(key)){
            //创建一个新节点
            Node* oneptr = new Node(key, value);
            hashmap[key]=oneptr;

            //新节点入头
            AddTohead(oneptr);
            n++;
            // 如果超长了,删除尾数据
            if(n>len){
                Node * temp = deletetail();
                //hash中去掉删除的key
                hashmap.erase(temp->key);
                //防止内存泄漏
                delete temp;
                --n;
            }
        }
        else{
            //否则修改旧的value即可
            Node * ptr = hashmap[key];
            ptr->value = value;
            MoveTohead(ptr);
        }
    }

    // 添加到头部,需要修改头节点的后指针,该节点的前后指针,旧第一个节点的前指针 共4个指针
    void AddTohead(Node * node){
        node->prex = head;
        node->next = head->next;
        head->next->prex = node;
        head->next = node;
    }

    // 删除双链表的指定节点,需要修改2个指针,即 前节点的后指针与 后节点的前指针
    void RemoveNode(Node* node){
        node->prex->next = node->next;
        node->next->prex = node->prex;
    }

    // 使用节点需要做两个事情,将链表的旧位置去掉,添加到链表头位置
    void MoveTohead(Node* node){
        RemoveNode(node);
        AddTohead(node);
    }

    // 删除尾节点
    Node* deletetail(){
        Node* temp = tail->prex;
        RemoveNode(temp);
        return temp;
    }

};

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

 

 

使用STL现成的结构

struct Node{
    int key;
    int value;
    Node(int a,int b):key(a),value(b){}
};

class LRUCache {

private:
    int len;
    int n;
    // 存放数据节点的双向链表
    list<Node> List;
    // hash表
    unordered_map<int, list<Node>::iterator> hashmap;

public:
    LRUCache(int capacity) {
        len=capacity;
        n=0;
    }
    
    int get(int key) {

        if(hashmap.find(key) == hashmap.end()){
            return -1;
        }

        List.splice(List.begin(), List, hashmap[key]);
        hashmap[key] = List.begin();
        return hashmap[key]->value;

    }
    
    void put(int key, int value) {

        // 如果没有找到这个节点了
        if(hashmap.find(key) == hashmap.end()){

            // 满了,删最后一个
            if(hashmap.size()==len){
                hashmap.erase(List.back().key);
                List.pop_back();
            }
            // 加入新的到头部
            List.push_front(Node(key, value));
            // hash表添加新的节点
            hashmap[key] = List.begin();

        }
        else{
            // 存在旧节点,更新value,同时改放到链表头
            hashmap[key]->value = value;
            List.splice(List.begin(), List, hashmap[key]);
            // hash表中也要更新下更新过value的节点
            hashmap[key] = List.begin();
        }  

    }
};

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

 

 

主要学习到list的splice函数

先看看这splice方法的三种声明:
(1)void splice ( iterator position, list<T,Allocator>& x );
功能: 将 list x 中的元素全都移到position处
(2)void splice ( iterator position, list<T,Allocator>& x, iterator it );
功能: 将 list x 中的由迭代器it指向的元素移到position处
(3)void splice ( iterator position, list<T,Allocator>& x, iterator first, iterator last );
功能:将 list x 中的从迭代器 first 到迭代器 last 这一段元素移动到position处

注意:position位置的指定只能是调用者容器中的位置,要剪切的元素是list x中元素
 

List.splice(List.begin(), List, hashmap[key]);

将List中的hashmap[key]移动到List.begin()的位置。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值