什么是 LRU


LRU Cache是一个Cache的置换算法,含义是“最近最少使用”,把满足“最近最少使用”的数据从Cache中剔除出去,并且保证Cache中第一个数据是最近刚刚访问的,因为这样的数据更有可能被接下来的程序所访问。

LRU的应用比较广泛,最基础的内存页置换中就用了,对了,这里有个概念要清楚一下,Cache不见得是CPU的高速缓存的那个Cache,这里的Cache直接翻译为缓存,就是两种存储方式的速度有比较大的差别,都可以用Cache缓存数据,比如硬盘明显比内存慢,所以常用的数据我们可以Cache在内存中。

LRU基本算法描述


前提:

  • 由于我只是简单实现一下这个算法,所以数据都用int代替,下一个版本会改成模板形式的,更加通用。

要求:

  • 只提供两个接口,一个获取数据getValue(key),一个写入数据putValue(key,value)
  • 无论是获取还是写入数据,当前这个数据要保持在最容易访问的位置
  • 缓存数量有限,最长时间没被访问的数据应该置换出缓存

算法:

为了满足上面几个条件,实际上可以用一个双向链表来实现,每次访问完数据(不管是获取还是写入),调整双向链表的顺序,把刚刚访问的数据调整到链表的最前方,以后再访问的时候速度将最快。

为了方便,提供一个头和一个尾节点,不存具体的数,链表的基本形式如下面的这个简单表述

Head <===> Node1 <===> Node2 <===> Node3 <===> Near

OK,就这么些,比较简单,实现起来也不难,用c++封装一个LRUCache类,类提供两个方法,分别是获取和更新,初始化类的时候传入Cache的节点数。

先定义一个存数据的节点数据结构

typedef struct _Node_{

	int key;    //键
int value; //数据 struct _Node_ *next; //下一个节点
struct _Node_ *pre; //上一个节点 }CacheNode;

类定义:

class LRUCache{

public:

	LRUCache(int cache_size=10);  //构造函数,默认cache大小为10
~LRUCache(); //析构函数 int getValue(int key); //获取值
bool putValue(int key,int value); //写入或更新值
void displayNodes(); //辅助函数,显示所有节点 private: int cache_size_; //cache长度
int cache_real_size_; //目前使用的长度
CacheNode *p_cache_list_head; //头节点指针
CacheNode *p_cache_list_near; //尾节点指针 void detachNode(CacheNode *node); //分离节点
void addToFront(CacheNode *node); //将节点插入到第一个 };

类实现:

LRUCache::LRUCache(int cache_size)
{
cache_size_=cache_size;
cache_real_size_=0;
p_cache_list_head=new CacheNode();
p_cache_list_near=new CacheNode();
p_cache_list_head->next=p_cache_list_near;
p_cache_list_head->pre=NULL;
p_cache_list_near->pre=p_cache_list_head;
p_cache_list_near->next=NULL; } LRUCache::~LRUCache()
{
CacheNode *p;
p=p_cache_list_head->next;
while(p!=NULL)
{
delete p->pre;
p=p->next;
} delete p_cache_list_near; } void LRUCache::detachNode(CacheNode *node)
{
node->pre->next=node->next;
node->next->pre=node->pre;
} void LRUCache::addToFront(CacheNode *node)
{
node->next=p_cache_list_head->next;
p_cache_list_head->next->pre=node;
p_cache_list_head->next=node;
node->pre=p_cache_list_head;
} int LRUCache::getValue(int key)
{
CacheNode *p=p_cache_list_head->next;
while(p->next!=NULL)
{ if(p->key == key) //catch node
{ detachNode(p);
addToFront(p);
return p->value;
}
p=p->next;
}
return -1;
} bool LRUCache::putValue(int key,int value)
{
CacheNode *p=p_cache_list_head->next;
while(p->next!=NULL)
{ if(p->key == key) //catch node
{
p->value=value;
getValue(key);
return true;
}
p=p->next;
} if(cache_real_size_ >= cache_size_)
{
cout << "free" <<endl;
p=p_cache_list_near->pre->pre;
delete p->next;
p->next=p_cache_list_near;
p_cache_list_near->pre=p;
} p=new CacheNode();//(CacheNode *)malloc(sizeof(CacheNode)); if(p==NULL)
return false; addToFront(p);
p->key=key;
p->value=value; cache_real_size_++; return true;
} void LRUCache::displayNodes()
{
CacheNode *p=p_cache_list_head->next; while(p->next!=NULL)
{
cout << " Key : " << p->key << " Value : " << p->value << endl;
p=p->next; }
cout << endl; }

说着后面的话


其实,程序还可以优化,首先,把数据int类型换成模板形式的通用类型,另外,数据查找的时候复杂度为O(n),可以换成hash表来存数据,链表只做置换处理,这样查找添加的时候速度将快很多。

LRU Cache的简单c++实现的更多相关文章

  1. LRU cache缓存简单实现

    LRU cache LRU(最近最少使用)是一种常用的缓存淘汰机制.当缓存大小容量到达最大分配容量的时候,就会将缓存中最近访问最少的对象删除掉,以腾出空间给新来的数据. 实现 (1)单线程简单版本 ( ...

  2. 基于LRU Cache的简单缓存

    package com.test.testCache; import java.util.Map; import org.json.JSONArray; import org.json.JSONExc ...

  3. [LeetCode] LRU Cache 最近最少使用页面置换缓存器

    Design and implement a data structure for Least Recently Used (LRU) cache. It should support the fol ...

  4. LeetCode——LRU Cache

    Description: Design and implement a data structure for Least Recently Used (LRU) cache. It should su ...

  5. LRU Cache

    LRU Cache 题目链接:https://oj.leetcode.com/problems/lru-cache/ Design and implement a data structure for ...

  6. LeetCode之LRU Cache 最近最少使用算法 缓存设计

    设计并实现最近最久未使用(Least Recently Used)缓存. 题目描述: Design and implement a data structure for Least Recently ...

  7. leetcode 146. LRU Cache ----- java

    esign and implement a data structure for Least Recently Used (LRU) cache. It should support the foll ...

  8. 【LeetCode】146. LRU Cache

    LRU Cache Design and implement a data structure for Least Recently Used (LRU) cache. It should suppo ...

  9. 设计并实现一个LRU Cache

    一.什么是Cache 1 概念 Cache,即高速缓存,是介于CPU和内存之间的高速小容量存储器.在金字塔式存储体系中它位于自顶向下的第二层,仅次于CPU寄存器.其容量远小于内存,但速度却可以接近CP ...

随机推荐

  1. 十二.200多万元得到的创业教训--app名字是关键

    摘要:当完毕了一个app后,就要须要上应用市场,以下讲一下起名和上应用市场的一些技巧. 健生干货分享:第12篇 1.必须是先上app store,再上其它应用市场 为啥要这样做?由于app store ...

  2. JavaScript学习(2)

    时间就像海绵里的水,要挤总还是有的,所以在最近不是太忙的时间里,我选择了挤时间,一点点的挤出了大把的时间,于是乎便迎来了我对javascript的第二阶段的学习,首先说下, 说起JavaScript大 ...

  3. Shell-WEB目录监控

    #!/bin/sh #date:2015-12-08 #filename:check_webfile.sh #作者:李兴利 #Email:1162572407@qq.com #version:v1.1 ...

  4. MySQL的MyISAM和InnoDB对比及优化(转)

    MyISAM和InnoDB是在使用MySQL最常用的两个表类型,各有优缺点,视具体应用而定.基本的差别为:MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持.MyISAM类型的表强调的是 ...

  5. django: db howto - 2

    继 django: db howto - 1 : 一 操作数据库的三种方式: [root@bogon csvt03]# python2.7 manage.py shell Python 2.7.5 ( ...

  6. css快捷方式

    本来是年前准备整理发布的,都搞定50%了,一篇万恶的<盗墓笔记:九幽将军>让我猪油蒙了心.....诶,不说了,搞一半就算了,最后还忘了保存,此刻只听得那一万只草某马呼啸而过... 言归正传 ...

  7. (转)passwordStrength 基于jquery的密码强度检测代码使用介绍

    使用很简单. 代码如下: $('#pass').passwordStrength();  XHTML 代码如下: <p><label>请输入密码:</label>  ...

  8. 实现类似QQ的折叠效果

    //  主要核心是点击自定义header来展开和收起每一组里面的cell,模型里面应该有isShow此属性来记录开展还是收起. //  ViewController.m//  实现类似QQ的折叠效果/ ...

  9. Linux 常用命令使用方法大搜刮

    Linux 常用命令使用方法大搜刮 1.# 表示权限用户(如:root),$ 表示普通用户  开机提示:Login:输入用户名  password:输入口令   用户是系统注册用户成功登陆后,可以进入 ...

  10. 3月25日 javascript练习

    1.找出100以内带7的数字 2.求1!+2!+3!+......+n!的和