LRU Cache基本原理----内存--文件--网络存储模型

LRU Cache基本原理

         Cache思想: 都是在给定一个限定大小的空间的前提下,设计一个原则如何来更新和访问其中元素

         

           LRU算法设计原则:如何一个数据在最近一段时间没有被访问到,那么在将来他被访问的可能性也很小。也就是说,当限定的空间已存满数据时,应当把最久没有被访问到的数据淘汰。

       

          现实中思维: 人类大脑存储的方式,例如,把人类大脑存储空间比作一个固定的大小的空间,存储的内存是电话号,总是能够先记住刚刚联系过的,而慢慢遗忘很久没有的访问的。

       

          Cache应用场景:客户端访问的服务器的三层架构    内存------> 本地文件 --------->网络

   

          Cache 数据结构:

          map 数据结构   主要的作用是:用来存储数据

          list   链表           主要的作用是:用来解决,删除的元素(次数最少访问的次数)

 

C++实现的代码

             

#include <iostream>
#include <map>
#include <algorithm>
using namespace std;
 
struct Node
{
    int key;
    int value;
    Node *next;
};
 
 
class LRUCache{
private:
    int count;
    int size ;
    map<int,Node *> mp;
    Node *cacheList;
public:
    LRUCache(int capacity) {
      size = capacity;
      cacheList = NULL;
      count = 0;
    }
     
    int get(int key) {
        if(cacheList==NULL)
            return -1;
        map<int,Node *>::iterator it=mp.find(key);
        if(it==mp.end())  //如果在Cache中不存在该key, 则返回-1
        {
            return -1; 
        }
        else
        {
            Node *p = it->second;   
            pushFront(p);    //将节点p置于链表头部
        }
        return cacheList->value;  
    }
     
    void set(int key, int value) {
        if(cacheList==NULL)   //如果链表为空,直接放在链表头部
        {
            cacheList = (Node *)malloc(sizeof(Node));
            cacheList->key = key;
            cacheList->value = value;
            cacheList->next = NULL;
            mp[key] = cacheList;
            count++;
        }
        else   //否则,在map中查找
        {
            map<int,Node *>::iterator it=mp.find(key);
            if(it==mp.end())   //没有命中
            {
                if(count == size)  //cache满了
                {
                    Node * p = cacheList;
                    Node *pre = p;
                    while(p->next!=NULL)
                    {
                        pre = p;
                        p= p->next; 
                    }
                    mp.erase(p->key);
                    count--;
                    if(pre==p)         //说明只有一个节点
                        p=NULL;
                    else
                        pre->next = NULL;
                    free(p);
                }
                Node * newNode = (Node *)malloc(sizeof(Node)); 
                newNode->key = key;
                newNode->value = value;
                 
                newNode->next = cacheList;
                cacheList = newNode;
                 
                mp[key] = cacheList;
                count++;   
            }
            else
            {
                Node *p = it->second;   
                p->value = value;
                pushFront(p);
            }
        }
         
    }
     
    void pushFront(Node *cur)   //单链表删除节点,并将节点移动链表头部,O(n)
    {
        if(count==1)
            return;
        if(cur==cacheList)
            return;
        Node *p = cacheList;
        while(p->next!=cur)
        {
            p=p->next;      
        }
        p->next = cur->next;   //删除cur节点
            
        cur->next = cacheList;
        cacheList = cur;
    }
     
    void printCache(){
         
        Node *p = cacheList;
        while(p!=NULL)
        {
            cout<<p->key<<" ";
            p=p->next;
        }
        cout<<endl;
    }
};
 
 
int main(void)
{
    /*LRUCache cache(3);
    cache.set(2,10);
    cache.printCache();
    cache.set(1,11);
    cache.printCache();
    cache.set(2,12);
    cache.printCache();
    cache.set(1,13);
    cache.printCache();
    cache.set(2,14);
    cache.printCache();
    cache.set(3,15);
    cache.printCache();
    cache.set(4,100);
    cache.printCache();
    cout<<cache.get(2)<<endl;
    cache.printCache();*/
     
    LRUCache cache(2);
    cout<<cache.get(2)<<endl;
    cache.set(2,6);
    cache.printCache();	//打印的KEY的值
    cout<<cache.get(1)<<endl;
    cache.set(1,5);
    cache.printCache();
    cache.set(1,2);
    cache.printCache();
    cout<<cache.get(1)<<endl;
    cout<<cache.get(2)<<endl;
    return 0;
}

上面的代码需要的改进的 

1.因为需要经常要访问链表 -----因此需要使用双链表

2.因为map内部实现的方式是list这里每一次查找类似于 遍历一次链表,因此效率低,采用的方法:hash_map的线(确定  浪费空间)

参考资料

http://flychao88.iteye.com/blog/1977653

猜你喜欢

转载自blog.csdn.net/qq_1335857320/article/details/82010745