TheAlgorithms/C++
1.0.0
All the algorithms implemented in C++
Toggle main menu visibility
Loading...
Searching...
No Matches
lfu_cache.cpp
Go to the documentation of this file.
1
22
23
#include <cassert>
// for assert
24
#include <iostream>
// for std::cout
25
#include <unordered_map>
// for std::unordered_map
26
31
namespace
others
{
32
37
namespace
Cache
{
38
44
template
<
typename
T>
45
class
D_Node {
46
public
:
47
T
data
;
48
D_Node<T> *
prev
;
49
D_Node<T> *
next
;
50
51
explicit
D_Node(T
data
) :
data
(
data
),
prev
(nullptr),
next
(nullptr) {}
52
};
53
54
template
<
typename
K,
typename
V>
55
using
CacheNode = D_Node<std::pair<K, V>>;
56
63
template
<
typename
K,
typename
V>
64
class
LFUCache
{
65
std::unordered_map<K, std::pair<CacheNode<K, V> *,
int
>>
66
node_map
;
67
std::unordered_map<int, std::pair<CacheNode<K, V> *, CacheNode<K, V> *>>
68
freq_map
;
69
70
int
minFreq
;
71
int
_capacity
;
72
73
public
:
78
explicit
LFUCache
(
int
_capacity
) :
minFreq
(0),
_capacity
(
_capacity
) {}
79
80
private
:
88
void
push
(
int
freq, CacheNode<K, V> *
node
) {
89
// if freq is not present, then make a new list with node as the head as
90
// well as tail.
91
if
(!
freq_map
.count(freq)) {
92
freq_map
[freq] = {
node
,
node
};
93
return
;
94
}
95
96
std::pair<CacheNode<K, V> *, CacheNode<K, V> *> &p =
freq_map
[freq];
97
98
// insert the node at the beginning of the linked list and update the
99
// head.
100
p.first->prev =
node
;
101
node
->next = p.first;
102
p.first =
node
;
103
}
104
109
void
increase_frequency
(std::pair<CacheNode<K, V> *,
int
> &p_node) {
110
CacheNode<K, V> *
node
= p_node.first;
111
int
freq = p_node.second;
112
113
std::pair<CacheNode<K, V> *, CacheNode<K, V> *> &p =
freq_map
[freq];
114
115
// if the given node is the only node in the list,
116
// then erase the frequency from map
117
// and increase minFreq by 1.
118
if
(p.first ==
node
&& p.second ==
node
) {
119
freq_map
.erase(freq);
120
if
(
minFreq
== freq) {
121
minFreq
= freq + 1;
122
}
123
}
else
{
124
// remove the given node from current freq linked list
125
CacheNode<K, V> *prev =
node
->prev;
126
CacheNode<K, V> *next =
node
->next;
127
node
->prev =
nullptr
;
128
node
->next =
nullptr
;
129
130
if
(prev) {
131
prev->
next
= next;
132
}
else
{
133
p.first = next;
134
}
135
136
if
(next) {
137
next->
prev
= prev;
138
}
else
{
139
p.second = prev;
140
}
141
}
142
push
(freq + 1,
node
);
143
++p_node.second;
144
}
145
149
void
pop
() {
150
std::pair<CacheNode<K, V> *, CacheNode<K, V> *> &p =
freq_map
[
minFreq
];
151
152
// if there is only one node
153
// remove the node and erase
154
// the frequency from freq_map
155
if
(p.first == p.second) {
156
delete
p.first;
157
freq_map
.erase(
minFreq
);
158
return
;
159
}
160
161
// remove the last node in the linked list
162
CacheNode<K, V> *temp = p.second;
163
p.second = temp->
prev
;
164
p.second->next =
nullptr
;
165
delete
temp;
166
}
167
168
public
:
174
void
put
(K key, V value) {
175
// update the value if key already exists
176
if
(
node_map
.count(key)) {
177
node_map
[key].first->data.second = value;
178
increase_frequency
(
node_map
[key]);
179
return
;
180
}
181
182
// if the cache is full
183
// remove the least frequently used item
184
if
(
node_map
.size() ==
_capacity
) {
185
node_map
.erase(
freq_map
[
minFreq
].second->data.first);
186
pop
();
187
}
188
189
// insert the new node and set minFreq to 1
190
CacheNode<K, V> *
node
=
new
CacheNode<K, V>({key, value});
191
node_map
[key] = {
node
, 1};
192
minFreq
= 1;
193
push
(1,
node
);
194
}
195
202
V
get
(K key) {
203
if
(!
node_map
.count(key)) {
204
throw
std::runtime_error(
"key is not present in the cache"
);
205
}
206
207
// increase the frequency and return the value
208
V value =
node_map
[key].first->data.second;
209
increase_frequency
(
node_map
[key]);
210
return
value;
211
}
212
217
int
size
()
const
{
return
node_map
.size(); }
218
223
int
capacity
()
const
{
return
_capacity
; }
224
229
bool
empty
()
const
{
return
node_map
.empty(); }
230
235
~LFUCache
() {
236
auto
it =
node_map
.begin();
237
while
(it !=
node_map
.end()) {
238
delete
it->second.first;
239
++it;
240
}
241
}
242
};
243
}
// namespace Cache
244
}
// namespace others
245
250
static
void
test
() {
251
others::Cache::LFUCache<int, int>
cache(5);
252
253
// test the initial state of the cache
254
assert(cache.
size
() == 0);
255
assert(cache.
capacity
() == 5);
256
assert(cache.
empty
());
257
258
// test insertion in the cache
259
cache.
put
(1, 10);
260
cache.
put
(-2, 20);
261
262
// test the state of cache after inserting some items
263
assert(cache.
size
() == 2);
264
assert(cache.
capacity
() == 5);
265
assert(!cache.
empty
());
266
267
// test getting items from the cache
268
assert(cache.
get
(1) == 10);
269
assert(cache.
get
(-2) == 20);
270
271
cache.
put
(-3, -30);
272
cache.
put
(4, 40);
273
cache.
put
(5, -50);
274
cache.
put
(6, 60);
275
276
// test the state after inserting more items than the capacity
277
assert(cache.
size
() == 5);
278
assert(cache.
capacity
() == 5);
279
assert(!cache.
empty
());
280
281
// test retrieval of all items in the cache
282
assert(cache.
get
(1) == 10);
283
assert(cache.
get
(-2) == 20);
284
285
// fetching -3 throws runtime_error
286
// as -3 was evicted being the least frequently used
287
// when 6 was added
288
// assert(cache.get(-3) == -30);
289
290
assert(cache.
get
(4) == 40);
291
assert(cache.
get
(5) == -50);
292
assert(cache.
get
(6) == 60);
293
294
std::cout <<
"test - passed\n"
;
295
}
296
301
int
main
() {
302
test
();
// run the self test implementation
303
return
0;
304
}
test
void test()
Definition
caesar_cipher.cpp:100
others::Cache::D_Node< std::pair< K, V > >::next
D_Node< std::pair< K, V > > * next
Definition
lfu_cache.cpp:49
others::Cache::D_Node< std::pair< K, V > >::prev
D_Node< std::pair< K, V > > * prev
Definition
lfu_cache.cpp:48
others::Cache::D_Node< std::pair< K, V > >::data
std::pair< K, V > data
Definition
lfu_cache.cpp:47
others::Cache::LFUCache
LFUCache.
Definition
lfu_cache.cpp:64
others::Cache::LFUCache::increase_frequency
void increase_frequency(std::pair< CacheNode< K, V > *, int > &p_node)
increase the frequency of node and push it in the respective list.
Definition
lfu_cache.cpp:109
others::Cache::LFUCache::_capacity
int _capacity
maximum capacity of the cache
Definition
lfu_cache.cpp:71
others::Cache::LFUCache::get
V get(K key)
get the value of the key-value pair if exists
Definition
lfu_cache.cpp:202
others::Cache::LFUCache::empty
bool empty() const
returns true if the cache is empty, false otherwise.
Definition
lfu_cache.cpp:229
others::Cache::LFUCache::minFreq
int minFreq
minimum frequency in the cache
Definition
lfu_cache.cpp:70
others::Cache::LFUCache::~LFUCache
~LFUCache()
destructs the cache, iterates on the map and deletes every node present in the cache.
Definition
lfu_cache.cpp:235
others::Cache::LFUCache::pop
void pop()
pop the last node in the least frequently used linked list
Definition
lfu_cache.cpp:149
others::Cache::LFUCache::freq_map
std::unordered_map< int, std::pair< CacheNode< K, V > *, CacheNode< K, V > * > > freq_map
maps the frequency to doubly linked list
Definition
lfu_cache.cpp:68
others::Cache::LFUCache::capacity
int capacity() const
Returns the total capacity of the cache.
Definition
lfu_cache.cpp:223
others::Cache::LFUCache::node_map
std::unordered_map< K, std::pair< CacheNode< K, V > *, int > > node_map
maps the key to the node address and frequency
Definition
lfu_cache.cpp:66
others::Cache::LFUCache::push
void push(int freq, CacheNode< K, V > *node)
push the node at first position in the linked list of given frequency
Definition
lfu_cache.cpp:88
others::Cache::LFUCache::size
int size() const
Returns the number of items present in the cache.
Definition
lfu_cache.cpp:217
others::Cache::LFUCache::put
void put(K key, V value)
upsert a key-value pair
Definition
lfu_cache.cpp:174
others::Cache::LFUCache::LFUCache
LFUCache(int _capacity)
Constructor, Initialize with minFreq and _capacity.
Definition
lfu_cache.cpp:78
main
int main()
Main function.
Definition
generate_parentheses.cpp:110
others::Cache
Cache algorithm.
Definition
lfu_cache.cpp:37
others
for vector
node
Definition
binary_search_tree.cpp:11
others
lfu_cache.cpp
Generated by
1.18.0