LRU cache Algorithm

Source: Internet
Author: User

LRU is short for Least Recently Used, which means it is Used at Least Recently. It is a Cache replacement algorithm.


Implementation: hashtable + two-way linked list
Time Complexity: insert, search, delete: O (1)
Space usage: O (N): A linked list stores K pieces of data (stl hash_map actually occupies a large space ).


Running environment:
Linux: redhat, fedora, centos, etc. (theoretically ubuntu, debian, mac OS, etc. can also be run)


Code:

#ifndef __LRUCACHE_H__#define __LRUCACHE_H__#include <vector>#include <ext/hash_map>#include <pthread.h>#include <assert.h>using namespace __gnu_cxx;template <class K, class D>struct Node{    K key;    D data;    Node *prev, *next;};template <class K, class D>class LRUCache{public:    LRUCache(size_t size , bool is_pthread_safe = false){        if(size <= 0)            size = 1024;        pthread_safe = is_pthread_safe;        if(pthread_safe)            pthread_mutex_init(&cached_mutex , NULL);        entries = new Node<K,D>[size];        for(size_t i = 0; i < size; ++i)            cached_entries.push_back(entries + i);        head = new Node<K,D>;        tail = new Node<K,D>;        head->prev = NULL;        head->next = tail;        tail->prev = head;        tail->next = NULL;    }    ~LRUCache(){        if(pthread_safe)            pthread_mutex_destroy(&cached_mutex);        delete head;        delete tail;        delete[] entries;    }    void Put(K key, D data);    D Get(K key);    private:    void cached_lock(void){        if(pthread_safe)            pthread_mutex_lock(&cached_mutex);    }    void cached_unlock(void){        if(pthread_safe)            pthread_mutex_unlock(&cached_mutex);    }    void detach(Node<K,D>* node){        node->prev->next = node->next;        node->next->prev = node->prev;    }    void attach(Node<K,D>* node){        node->prev = head;        node->next = head->next;        head->next = node;        node->next->prev = node;    }private:    hash_map<K, Node<K,D>* > cached_map;    vector<Node<K,D>* > cached_entries;    Node<K,D> * head, *tail;    Node<K,D> * entries;    bool pthread_safe;    pthread_mutex_t cached_mutex;};template<class K , class D>void LRUCache<K,D>::Put(K key , D data){    cached_lock();    Node<K,D> *node = cached_map[key];    if(node){        detach(node);        node->data = data;        attach(node);    }    else{        if(cached_entries.empty()){            node = tail->prev;            detach(node);            cached_map.erase(node->key);        }        else{            node = cached_entries.back();            cached_entries.pop_back();        }        node->key = key;        node->data = data;        cached_map[key] = node;        attach(node);    }    cached_unlock();}template<class K , class D>D LRUCache<K,D>::Get(K key){    cached_lock();    Node<K,D> *node = cached_map[key];    if(node){        detach(node);        attach(node);        cached_unlock();        return node->data;    }    else{        cached_unlock();        return D();    }}#endif

Test cases:

/*Compile:  g++ -o app app.cpp LRUCache.cpp -lpthreadRun:  ./app*/#include <iostream>#include <string>#include "LRUCache.h"using namespace std;int main(void){    //int k = 10 ,    //    max = 100;    int k = 100000 ,        max = 1000000;    LRUCache<int , int> * lru_cache = new LRUCache<int , int>(k , true);        int tmp = 0;    for(int i = 0 ; i < 2*k ; ++i){        tmp = rand() % max;        lru_cache->Put(tmp, tmp + 1000000);        cout<<tmp<<endl;    }    for(int i = 0 ; i < k ; ++i){        tmp = rand() % max;        if(lru_cache->Get(tmp) == 0)            cout<<"miss : "<<tmp<<endl;        else            cout<<"hit  : "<<tmp<<"  value : "<<lru_cache->Get(tmp)<<endl;    }    delete lru_cache;    return 0;}


In fact, the above Code has some problems. I will continue to improve in the next day.

For example:

1: redundant operations. Cached_entries can be replaced by a counter.

2: excessive abstraction.

3: The Get and Put interfaces are unreasonable. If you implement the LRU cache of a disk block, you will find that the previous interface needs to be rewritten.


But for everyone to understand the LRU algorithm. It should be helpful.



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.