TheAlgorithms/C++
1.0.0
All the algorithms implemented in C++
Toggle main menu visibility
Loading...
Searching...
No Matches
lru_cache2.cpp
Go to the documentation of this file.
1
18
19
#include <cassert>
// for assert
20
#include <cstdint>
// for std::uint32_t
21
#include <iostream>
// for std::cout
22
#include <unordered_map>
// for std::unordered_map
23
28
namespace
others
{
29
34
namespace
Cache
{
35
41
template
<
typename
T>
42
class
D_Node
{
43
public
:
44
T
data
;
45
D_Node<T> *
prev
;
46
D_Node<T> *
next
;
47
48
explicit
D_Node(T
data
) :
data
(
data
),
prev
(nullptr),
next
(nullptr) {}
49
};
50
51
template
<
typename
K,
typename
V>
52
using
CacheNode =
D_Node<std::pair<K, V>
>;
53
60
template
<
typename
K,
typename
V>
61
class
LRUCache
{
62
CacheNode<K, V> *
head
;
63
CacheNode<K, V> *
tail
;
64
std::uint32_t
_capacity
;
65
66
std::unordered_map<K, CacheNode<K, V> *>
67
node_map
;
68
69
public
:
75
explicit
LRUCache
(
int
_capacity
)
76
:
head
(nullptr),
tail
(nullptr),
_capacity
(
_capacity
) {}
77
78
private
:
83
void
push_front
(CacheNode<K, V> *node_ptr) {
84
if
(!
head
) {
85
head
= node_ptr;
86
tail
= node_ptr;
87
return
;
88
}
89
90
node_ptr->
next
=
head
;
91
head
->prev = node_ptr;
92
head
= node_ptr;
93
}
94
99
void
make_recent
(CacheNode<K, V> *node_ptr) {
100
if
(
head
== node_ptr) {
101
return
;
102
}
103
104
CacheNode<K, V> *prev = node_ptr->
prev
;
105
CacheNode<K, V> *next = node_ptr->
next
;
106
107
prev->
next
= next;
108
if
(next) {
109
next->
prev
= prev;
110
}
else
{
111
tail
= prev;
112
}
113
114
node_ptr->
prev
=
nullptr
;
115
node_ptr->
next
=
nullptr
;
116
push_front
(node_ptr);
117
}
118
122
void
pop_back
() {
123
if
(!
head
) {
124
return
;
125
}
126
if
(
head
==
tail
) {
127
delete
head
;
128
head
=
nullptr
;
129
tail
=
nullptr
;
130
return
;
131
}
132
133
CacheNode<K, V> *temp =
tail
;
134
tail
=
tail
->
prev
;
135
tail
->
next
=
nullptr
;
136
delete
temp;
137
}
138
139
public
:
145
void
put
(K key, V value) {
146
// update the value if key already exists
147
if
(
node_map
.count(key)) {
148
node_map
[key]->data.second = value;
149
make_recent
(
node_map
[key]);
150
return
;
151
}
152
153
// if the cache is full
154
// remove the least recently used item
155
if
(
node_map
.size() ==
_capacity
) {
156
node_map
.erase(
tail
->
data
.first);
157
pop_back
();
158
}
159
160
CacheNode<K, V> *newNode =
new
CacheNode<K, V>({key, value});
161
162
node_map
[key] = newNode;
163
push_front
(newNode);
164
}
165
172
V
get
(K key) {
173
if
(!
node_map
.count(key)) {
174
throw
std::runtime_error(
"key is not present in the cache"
);
175
}
176
177
// move node to the beginning of the list
178
V value =
node_map
[key]->data.second;
179
make_recent
(
node_map
[key]);
180
return
value;
181
}
182
187
int
size
()
const
{
return
node_map
.size(); }
188
193
int
capacity
()
const
{
return
_capacity
; }
194
199
bool
empty
()
const
{
return
node_map
.empty(); }
200
205
~LRUCache
() {
206
auto
it =
node_map
.begin();
207
while
(it !=
node_map
.end()) {
208
delete
it->second;
209
++it;
210
}
211
}
212
};
213
}
// namespace Cache
214
}
// namespace others
215
220
static
void
test
() {
221
others::Cache::LRUCache<int, int>
cache(5);
222
223
// test the initial state of the cache
224
assert(cache.
size
() == 0);
225
assert(cache.
capacity
() == 5);
226
assert(cache.
empty
());
227
228
// test insertion in the cache
229
cache.
put
(1, 10);
230
cache.
put
(-2, 20);
231
232
// test the state of cache after inserting some items
233
assert(cache.
size
() == 2);
234
assert(cache.
capacity
() == 5);
235
assert(!cache.
empty
());
236
237
// test getting items from the cache
238
assert(cache.
get
(1) == 10);
239
assert(cache.
get
(-2) == 20);
240
241
cache.
put
(-3, -30);
242
cache.
put
(4, 40);
243
cache.
put
(5, -50);
244
cache.
put
(6, 60);
245
246
// test the state after inserting more items than the capacity
247
assert(cache.
size
() == 5);
248
assert(cache.
capacity
() == 5);
249
assert(!cache.
empty
());
250
251
// fetching 1 throws runtime_error
252
// as 1 was evicted being the least recently used
253
// when 6 was added
254
try
{
255
cache.
get
(1);
256
}
catch
(
const
std::runtime_error &e) {
257
assert(std::string(e.what()) ==
"key is not present in the cache"
);
258
}
259
260
// test retrieval of all items in the cache
261
assert(cache.
get
(-2) == 20);
262
assert(cache.
get
(-3) == -30);
263
assert(cache.
get
(4) == 40);
264
assert(cache.
get
(5) == -50);
265
assert(cache.
get
(6) == 60);
266
267
std::cout <<
"test - passed\n"
;
268
}
269
274
int
main
() {
275
test
();
// run the self test implementation
276
return
0;
277
}
test
void test()
Definition
caesar_cipher.cpp:100
others::Cache::D_Node
Node for a doubly linked list with data, prev and next pointers.
Definition
lfu_cache.cpp:45
others::Cache::D_Node::next
D_Node< T > * next
next node in the doubly linked list
Definition
lfu_cache.cpp:49
others::Cache::D_Node::prev
D_Node< T > * prev
previous node in the doubly linked list
Definition
lfu_cache.cpp:48
others::Cache::D_Node::data
T data
data of the node
Definition
lfu_cache.cpp:47
others::Cache::LRUCache
LRUCache.
Definition
lru_cache2.cpp:61
others::Cache::LRUCache::head
CacheNode< K, V > * head
head of the doubly linked list
Definition
lru_cache2.cpp:62
others::Cache::LRUCache::size
int size() const
Returns the number of items present in the cache.
Definition
lru_cache2.cpp:187
others::Cache::LRUCache::push_front
void push_front(CacheNode< K, V > *node_ptr)
push the node to the front of the linked list.
Definition
lru_cache2.cpp:83
others::Cache::LRUCache::tail
CacheNode< K, V > * tail
tail of the doubly linked list
Definition
lru_cache2.cpp:63
others::Cache::LRUCache::put
void put(K key, V value)
upsert a key-value pair
Definition
lru_cache2.cpp:145
others::Cache::LRUCache::~LRUCache
~LRUCache()
destructs the cache, iterates on the map and deletes every node present in the cache.
Definition
lru_cache2.cpp:205
others::Cache::LRUCache::LRUCache
LRUCache(int _capacity)
Constructor, Initialize the head and tail pointers to nullptr and initialize the _capacity of the cac...
Definition
lru_cache2.cpp:75
others::Cache::LRUCache::node_map
std::unordered_map< K, CacheNode< K, V > * > node_map
maps the key to the node address
Definition
lru_cache2.cpp:67
others::Cache::LRUCache::pop_back
void pop_back()
pop the last node in the linked list.
Definition
lru_cache2.cpp:122
others::Cache::LRUCache::empty
bool empty() const
returns whether the cache is empty or not
Definition
lru_cache2.cpp:199
others::Cache::LRUCache::get
V get(K key)
get the value of the key-value pair if exists
Definition
lru_cache2.cpp:172
others::Cache::LRUCache::make_recent
void make_recent(CacheNode< K, V > *node_ptr)
move the existing node in the list to the beginning of the list.
Definition
lru_cache2.cpp:99
others::Cache::LRUCache::_capacity
std::uint32_t _capacity
maximum capacity of the cache
Definition
lru_cache2.cpp:64
others::Cache::LRUCache::capacity
int capacity() const
Returns the total capacity of the cache.
Definition
lru_cache2.cpp:193
main
int main()
Main function.
Definition
generate_parentheses.cpp:110
others::Cache
Cache algorithm.
Definition
lfu_cache.cpp:37
others
for vector
others
lru_cache2.cpp
Generated by
1.18.0