Skip to content

Commit eb0ba7d

Browse files
committed
create rep
add LRUCache
0 parents  commit eb0ba7d

File tree

4 files changed

+287
-0
lines changed

4 files changed

+287
-0
lines changed

Doc/LRUCache.md

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
2+
## LRUCache ##
3+
===
4+
5+
### 什么是 LRU ###
6+
---
7+
8+
[LRU Cache](http://baike.baidu.com/link?url=axLw9G-1uuyndDPpTwTnAuktgy1kSRm1vb_2o5nWuy04gOXUjHFjJ4mM0rgxNRJ3)是一个Cache的置换算法,含义是“最近最少使用”,把满足“最近最少使用”的数据从Cache中剔除出去,并且保证Cache中第一个数据是最近刚刚访问的,因为这样的数据更有可能被接下来的程序所访问。
9+
10+
LRU的应用比较广泛,最基础的内存页置换中就用了,对了,这里有个概念要清楚一下,Cache不见得是CPU的高速缓存的那个Cache,这里的Cache直接翻译为缓存,就是两种存储方式的速度有比较大的差别,都可以用Cache缓存数据,比如硬盘明显比内存慢,所以常用的数据我们可以Cache在内存中。
11+
12+
13+
### LRU基本算法描述 ###
14+
15+
---
16+
17+
前提:
18+
19+
- 由于我只是简单实现一下这个算法,所以数据都用int代替,下一个版本会改成模板形式的,更加通用。
20+
21+
要求:
22+
23+
- 只提供两个接口,一个获取数据getValue(key),一个写入数据putValue(key,value)
24+
- 无论是获取还是写入数据,当前这个数据要保持在最容易访问的位置
25+
- 缓存数量有限,最长时间没被访问的数据应该置换出缓存
26+
27+
算法:
28+
29+
为了满足上面几个条件,实际上可以用一个双向链表来实现,每次访问完数据(不管是获取还是写入),调整双向链表的顺序,把刚刚访问的数据调整到链表的最前方,以后再访问的时候速度将最快。
30+
31+
为了方便,提供一个头和一个尾节点,不存具体的数,链表的基本形式如下面的这个简单表述
32+
33+
Head <===> Node1 <===> Node2 <===> Node3 <===> Near
34+
35+
OK,就这么些,比较简单,实现起来也不难,用c++封装一个LRUCache类,类提供两个方法,分别是获取和更新,初始化类的时候传入Cache的节点数。
36+
37+
[http://blog.csdn.net/ygrx/article/details/11105755](http://blog.csdn.net/ygrx/article/details/11105755)

readme.md

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
## My Code Lib ##
2+
3+
---
4+
5+
这是自己写的一些代码库。
6+
7+
- 代码都在src文件夹下
8+
- 说明在Doc文件夹下
9+
10+
一般的每个代码库描述都在[我的博客](http://blog.csdn.net/ygrx)上可以找到。
11+

src/LRUCache.cc

+184
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
2+
3+
#include "LRUCache.h"
4+
#include <stdio.h>
5+
#include <stdlib.h>
6+
#include <string.h>
7+
8+
//#include <hash_map>
9+
#if __GNUC__>2
10+
#include <ext/hash_map>
11+
using __gnu_cxx::hash_map;
12+
#else
13+
#include <hash_map>
14+
#endif
15+
16+
17+
LRUCache::LRUCache(int cache_size)
18+
{
19+
cache_size_=cache_size;
20+
cache_real_size_=0;
21+
p_cache_list_head=new CacheNode();
22+
p_cache_list_near=new CacheNode();
23+
p_cache_list_head->next=p_cache_list_near;
24+
p_cache_list_head->pre=NULL;
25+
p_cache_list_near->pre=p_cache_list_head;
26+
p_cache_list_near->next=NULL;
27+
28+
}
29+
30+
LRUCache::~LRUCache()
31+
{
32+
CacheNode *p;
33+
p=p_cache_list_head->next;
34+
while(p!=NULL)
35+
{
36+
delete p->pre;
37+
p=p->next;
38+
}
39+
40+
delete p_cache_list_near;
41+
42+
}
43+
44+
45+
void LRUCache::detachNode(CacheNode *node)
46+
{
47+
node->pre->next=node->next;
48+
node->next->pre=node->pre;
49+
}
50+
51+
void LRUCache::addToFront(CacheNode *node)
52+
{
53+
node->next=p_cache_list_head->next;
54+
p_cache_list_head->next->pre=node;
55+
p_cache_list_head->next=node;
56+
node->pre=p_cache_list_head;
57+
}
58+
59+
60+
int LRUCache::getValue(int key)
61+
{
62+
CacheNode *p=p_cache_list_head->next;
63+
while(p->next!=NULL)
64+
{
65+
66+
if(p->key == key) //catch node
67+
{
68+
69+
detachNode(p);
70+
addToFront(p);
71+
return p->value;
72+
}
73+
p=p->next;
74+
}
75+
return -1;
76+
}
77+
78+
79+
80+
bool LRUCache::putValue(int key,int value)
81+
{
82+
CacheNode *p=p_cache_list_head->next;
83+
while(p->next!=NULL)
84+
{
85+
86+
87+
if(p->key == key) //catch node
88+
{
89+
p->value=value;
90+
getValue(key);
91+
return true;
92+
}
93+
p=p->next;
94+
}
95+
96+
97+
if(cache_real_size_ >= cache_size_)
98+
{
99+
cout << "free" <<endl;
100+
p=p_cache_list_near->pre->pre;
101+
delete p->next;
102+
p->next=p_cache_list_near;
103+
p_cache_list_near->pre=p;
104+
}
105+
106+
p=new CacheNode();//(CacheNode *)malloc(sizeof(CacheNode));
107+
108+
if(p==NULL)
109+
return false;
110+
111+
addToFront(p);
112+
p->key=key;
113+
p->value=value;
114+
115+
cache_real_size_++;
116+
117+
return true;
118+
}
119+
120+
121+
void LRUCache::displayNodes()
122+
{
123+
CacheNode *p=p_cache_list_head->next;
124+
125+
while(p->next!=NULL)
126+
{
127+
cout << " Key : " << p->key << " Value : " << p->value << endl;
128+
p=p->next;
129+
130+
}
131+
cout << endl;
132+
133+
}
134+
135+
136+
int main()
137+
{
138+
139+
LRUCache *cache=new LRUCache(9);
140+
141+
cache->putValue(1,1);
142+
cache->putValue(2,2);
143+
cache->putValue(3,3);
144+
cache->putValue(4,3);
145+
cache->putValue(5,2);
146+
cache->displayNodes();
147+
148+
cout << cache->getValue(4) << endl;
149+
cache->displayNodes();
150+
//cache->displayNodes();
151+
cout << cache->getValue(3) << endl;
152+
cache->displayNodes();
153+
cout << cache->getValue(3) << endl;
154+
cache->displayNodes();
155+
cout << cache->getValue(1) << endl;
156+
cache->displayNodes();
157+
cout << cache->getValue(2) << endl;
158+
cache->displayNodes();
159+
cout << cache->getValue(9) << endl;
160+
161+
cache->displayNodes();
162+
163+
cache->putValue(4,9);
164+
//cout << cache->getValue(2) << endl;
165+
//cout << cache->getValue(3) << endl;
166+
cache->displayNodes();
167+
cout << cache->getValue(4) << endl;
168+
cache->displayNodes();
169+
cout << cache->getValue(2) << endl;
170+
cache->displayNodes();
171+
172+
delete cache;
173+
174+
return 1;
175+
}
176+
177+
178+
179+
180+
181+
182+
183+
184+

src/LRUCache.h

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
3+
LRU Cache
4+
5+
*/
6+
7+
#ifndef _LRUCACHE_
8+
#define _LRUCACHE_
9+
10+
11+
#include <iostream>
12+
#include <string>
13+
14+
using namespace std;
15+
16+
typedef struct _Node_{
17+
18+
int key;
19+
int value;
20+
21+
struct _Node_ *next;
22+
struct _Node_ *pre;
23+
24+
}CacheNode;
25+
26+
27+
28+
class LRUCache{
29+
30+
public:
31+
32+
LRUCache(int cache_size=10);
33+
~LRUCache();
34+
35+
36+
int getValue(int key);
37+
bool putValue(int key,int value);
38+
void displayNodes();
39+
40+
41+
private:
42+
43+
int cache_size_;
44+
int cache_real_size_;
45+
CacheNode *p_cache_list_head;
46+
CacheNode *p_cache_list_near;
47+
48+
void detachNode(CacheNode *node);
49+
void addToFront(CacheNode *node);
50+
51+
};
52+
53+
54+
55+
#endif

0 commit comments

Comments
 (0)