LRU cache

  LRU是Least Recently Used的縮寫,意思是最近最少使用,它是一種Cache替換算法。如今要設計一種數據結構有以下幾種性質:算法

1. 每一個節點爲一對key,value的形式,可經過get <key>查找,經過put <key, value> 插入數據結構

2. 最大存儲節點數爲nide

3. put操做時,若是已經存儲了n個節點,則要淘汰最近最少使用的那個節點性能

 

可能會有不少種解決方案,例如:優化

1、用一個雙向鏈表來存儲全部節點,get時,遍歷整個鏈表,找到對應的節點,而且把該節點挪動到鏈表的第一個位置,所以,連接中越靠前的位置老是距離最後一次訪問時間越短的節點,越靠後的位置老是距離最後一次訪問時間約久的節點。因此put時,若是已達到最大存儲節點數時,直接刪除鏈表最後一個節點再插入便可。總結,優勢:實現簡單,put操做的時間複雜度爲O(1) 缺點:get操做時間複雜度爲O(n),不夠優秀。this

2、咱們都知道哈希表這種數據結構查詢的時間性能很好,可是在這裏若是隻用一個哈希表,雖然查詢和插入操做都能優化到O(1),可是在刪除,也就是查找最近最少使用的節點時,卻不得不遍歷整個哈希表。咱們來作進一步優化,前面第一種方案刪除和插入操做都是O(1)的,可是查詢操做是O(n),若是能把這兩種方案結合一下的話,三種操做不就都是O(1)時間複雜度了。怎麼結合呢?spa

    哈希表的value存儲節點的指針,同時把全部的value鏈接成一個雙向鏈表,查詢操做時,經過哈希表直接找到這個節點的指針,同時,能夠在O(1)時間將這個節點移動到鏈表頭部,刪除操做時,直接刪除鏈表尾部那個節點,同時將這個節點從哈希表中刪除。設計

C++實現(這裏爲了簡化操做,直接用了STL的map代替哈希表)指針

class LRUCache {
public:
    struct Node {
        int key, value;
        Node *next, *pre;
    };
    map<int, Node*> cache;
    Node *head, *rear;
    int size;
    
    LRUCache(int capacity) {
        size = capacity;
        head = new Node();
        rear = new Node();
        head->pre = NULL;
        head->next = rear;
        rear->next = NULL;
        rear->pre = head;
    }

    int get(int key) {
        if(cache.find(key) == cache.end()) return -1;
        Node *tmp = cache[key];
        tmp->pre->next = tmp->next;
        tmp->next->pre = tmp->pre;

        head->next->pre = tmp;
        tmp->next = head->next;
        tmp->pre = head;
        head->next = tmp;
        return tmp->value;
    }

    void lru_delete() {
        if(cache.size() == 0) return;
        Node* tmp = rear->pre;
        rear->pre = tmp->pre;
        tmp->pre->next = rear;
        cache.erase(tmp->key);
        delete tmp;
    }

    void put(int key, int value) {
        // if the key exist, then just update the value
        if(cache.find(key) != cache.end()) {
            cache[key]->value = value;
            this->get(key);
            return;
        }

        if(cache.size() >= this->size) this->lru_delete();

        Node *tmp = new Node;
        tmp->key = key;
        tmp->value = value;
        tmp->pre = this->head;
        tmp->next = this->head->next;
        if(head->next != NULL) head->next->pre = tmp;
        this->head->next = tmp;
        cache.insert(pair<int, Node*>(key, tmp));
    }
};
View Code
相關文章
相關標籤/搜索