LRU缓存算法 - C++版

来源:互联网 发布:拙心网络米汤 编辑:程序博客网 时间:2024/06/17 20:10

LRU是Least Recently Used的缩写,意思是最近最少使用,它是一种Cache替换算法。 


实现思路:   hashtable + 双向链表
时间复杂度:    插入,查找,删除:O(1)
空间使用情况:  O(N) :一个链表存储K个数据(stl的hash_map实际占的空间比较大).


运行环境:
     linux:redhat , fedora ,centos等(理论上ubuntu , debian,mac os等也可以运行)


代码:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #ifndef __LRUCACHE_H__  
  2. #define __LRUCACHE_H__  
  3.   
  4. #include <vector>  
  5. #include <ext/hash_map>  
  6. #include <pthread.h>  
  7. #include <assert.h>  
  8.   
  9. using namespace __gnu_cxx;  
  10.   
  11. template <class K, class D>  
  12. struct Node{  
  13.     K key;  
  14.     D data;  
  15.     Node *prev, *next;  
  16. };  
  17.   
  18. template <class K, class D>  
  19. class LRUCache{  
  20. public:  
  21.     LRUCache(size_t size , bool is_pthread_safe = false){  
  22.         if(size <= 0)  
  23.             size = 1024;  
  24.   
  25.         pthread_safe = is_pthread_safe;  
  26.         if(pthread_safe)  
  27.             pthread_mutex_init(&cached_mutex , NULL);  
  28.   
  29.         entries = new Node<K,D>[size];  
  30.         for(size_t i = 0; i < size; ++i)  
  31.             cached_entries.push_back(entries + i);  
  32.   
  33.         head = new Node<K,D>;  
  34.         tail = new Node<K,D>;  
  35.         head->prev = NULL;  
  36.         head->next = tail;  
  37.         tail->prev = head;  
  38.         tail->next = NULL;  
  39.     }  
  40.   
  41.     ~LRUCache(){  
  42.         if(pthread_safe)  
  43.             pthread_mutex_destroy(&cached_mutex);  
  44.         delete head;  
  45.         delete tail;  
  46.         delete[] entries;  
  47.     }  
  48.   
  49.     void Put(K key, D data);  
  50.     D Get(K key);  
  51.       
  52. private:  
  53.     void cached_lock(void){  
  54.         if(pthread_safe)  
  55.             pthread_mutex_lock(&cached_mutex);  
  56.     }  
  57.     void cached_unlock(void){  
  58.         if(pthread_safe)  
  59.             pthread_mutex_unlock(&cached_mutex);  
  60.     }  
  61.     void detach(Node<K,D>* node){  
  62.         node->prev->next = node->next;  
  63.         node->next->prev = node->prev;  
  64.     }  
  65.     void attach(Node<K,D>* node){  
  66.         node->prev = head;  
  67.         node->next = head->next;  
  68.         head->next = node;  
  69.         node->next->prev = node;  
  70.     }  
  71.   
  72. private:  
  73.     hash_map<K, Node<K,D>* > cached_map;  
  74.     vector<Node<K,D>* > cached_entries;  
  75.     Node<K,D> * head, *tail;  
  76.     Node<K,D> * entries;  
  77.     bool pthread_safe;  
  78.     pthread_mutex_t cached_mutex;  
  79. };  
  80.   
  81. template<class K , class D>  
  82. void LRUCache<K,D>::Put(K key , D data){  
  83.     cached_lock();  
  84.     Node<K,D> *node = cached_map[key];  
  85.     if(node){  
  86.         detach(node);  
  87.         node->data = data;  
  88.         attach(node);  
  89.     }  
  90.     else{  
  91.         if(cached_entries.empty()){  
  92.             node = tail->prev;  
  93.             detach(node);  
  94.             cached_map.erase(node->key);  
  95.         }  
  96.         else{  
  97.             node = cached_entries.back();  
  98.             cached_entries.pop_back();  
  99.         }  
  100.         node->key = key;  
  101.         node->data = data;  
  102.         cached_map[key] = node;  
  103.         attach(node);  
  104.     }  
  105.     cached_unlock();  
  106. }  
  107.   
  108. template<class K , class D>  
  109. D LRUCache<K,D>::Get(K key){  
  110.     cached_lock();  
  111.     Node<K,D> *node = cached_map[key];  
  112.     if(node){  
  113.         detach(node);  
  114.         attach(node);  
  115.         cached_unlock();  
  116.         return node->data;  
  117.     }  
  118.     else{  
  119.         cached_unlock();  
  120.         return D();  
  121.     }  
  122. }  
  123.   
  124. #endif  

测试用例:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /* 
  2. Compile: 
  3.   g++ -o app app.cpp LRUCache.cpp -lpthread 
  4. Run: 
  5.   ./app 
  6. */  
  7. #include <iostream>  
  8. #include <string>  
  9.   
  10. #include "LRUCache.h"  
  11.   
  12. using namespace std;  
  13.   
  14. int   
  15. main(void){  
  16.     //int k = 10 ,  
  17.     //    max = 100;  
  18.     int k = 100000 ,  
  19.         max = 1000000;  
  20.     LRUCache<int , int> * lru_cache = new LRUCache<int , int>(k , true);  
  21.       
  22.     int tmp = 0;  
  23.     for(int i = 0 ; i < 2*k ; ++i){  
  24.         tmp = rand() % max;  
  25.         lru_cache->Put(tmp, tmp + 1000000);  
  26.         cout<<tmp<<endl;  
  27.     }  
  28.   
  29.     for(int i = 0 ; i < k ; ++i){  
  30.         tmp = rand() % max;  
  31.         if(lru_cache->Get(tmp) == 0)  
  32.             cout<<"miss : "<<tmp<<endl;  
  33.         else  
  34.             cout<<"hit  : "<<tmp<<"  value : "<<lru_cache->Get(tmp)<<endl;  
  35.     }  
  36.   
  37.     delete lru_cache;  
  38.     return 0;  
  39. }  
0 0
原创粉丝点击