Skip to content

Commit e646b45

Browse files
authored
Added LRU Cache (#219)
1 parent 2e139cc commit e646b45

File tree

1 file changed

+126
-0
lines changed

1 file changed

+126
-0
lines changed

Cache/LRUCache.js

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
class DoubleLinkedListNode {
2+
// Double Linked List Node built specifically for LRU Cache
3+
constructor (key, val) {
4+
this.key = key
5+
this.val = val
6+
this.next = null
7+
this.prev = null
8+
}
9+
}
10+
11+
class DoubleLinkedList {
12+
// Double Linked List built specifically for LRU Cache
13+
constructor () {
14+
this.head = new DoubleLinkedListNode(null, null)
15+
this.rear = new DoubleLinkedListNode(null, null)
16+
this.head.next = this.rear
17+
this.rear.prev = this.head
18+
}
19+
20+
add (node) {
21+
// Adds the given node to the end of the list (before rear)
22+
const temp = this.rear.prev
23+
temp.next = node
24+
node.prev = temp
25+
this.rear.prev = node
26+
node.next = this.rear
27+
}
28+
29+
remove (node) {
30+
// Removes and returns the given node from the list
31+
const tempLast = node.prev
32+
const tempNext = node.next
33+
node.prev = null
34+
node.next = null
35+
tempLast.next = tempNext
36+
tempNext.prev = tempLast
37+
38+
return node
39+
}
40+
}
41+
42+
class LRUCache {
43+
// LRU Cache to store a given capacity of data
44+
constructor (capacity) {
45+
this.list = new DoubleLinkedList()
46+
this.capacity = capacity
47+
this.numKeys = 0
48+
this.hits = 0
49+
this.miss = 0
50+
this.cache = {}
51+
}
52+
53+
cacheInfo () {
54+
// Return the details for the cache instance [hits, misses, capacity, current_size]
55+
return `CacheInfo(hits=${this.hits}, misses=${this.miss}, capacity=${this.capacity}, current size=${this.numKeys})`
56+
}
57+
58+
set (key, value) {
59+
// Sets the value for the input key and updates the Double Linked List
60+
if (!(key in this.cache)) {
61+
if (this.numKeys >= this.capacity) {
62+
const keyToDelete = this.list.head.next.key
63+
this.list.remove(this.cache[keyToDelete])
64+
delete this.cache[keyToDelete]
65+
this.numKeys -= 1
66+
}
67+
this.cache[key] = new DoubleLinkedListNode(key, value)
68+
this.list.add(this.cache[key])
69+
this.numKeys += 1
70+
} else {
71+
const node = this.list.remove(this.cache[key])
72+
node.val = value
73+
this.list.add(node)
74+
}
75+
}
76+
77+
get (key) {
78+
// Returns the value for the input key and updates the Double Linked List. Returns null if key is not present in cache
79+
if (key in this.cache) {
80+
this.hits += 1
81+
this.list.add(this.list.remove(this.cache[key]))
82+
return this.cache[key].val
83+
}
84+
this.miss += 1
85+
return null
86+
}
87+
}
88+
89+
function main () {
90+
// Example 1 (Small Cache)
91+
const cache = new LRUCache(2)
92+
cache.set(1, 1)
93+
cache.set(2, 2)
94+
95+
console.log(cache.get(1))
96+
97+
cache.set(3, 3)
98+
99+
console.log(cache.get(2)) // cache miss
100+
101+
cache.set(4, 4)
102+
103+
console.log(cache.get(1)) // cache miss
104+
console.log(cache.get(3))
105+
console.log(cache.get(4))
106+
107+
console.log('Example Cache: ', cache.cacheInfo(), '\n')
108+
109+
// Example 2 (Computing Fibonacci Series - 100 terms)
110+
function fib (num, cache = null) {
111+
if (cache) {
112+
const value = cache.get(num)
113+
if (value) { return value }
114+
}
115+
if (num === 1 || num === 2) { return 1 }
116+
const result = fib(num - 1, cache) + fib(num - 2, cache)
117+
if (cache) { cache.set(num, result) }
118+
return result
119+
}
120+
121+
const fibCache = new LRUCache(100)
122+
for (let i = 1; i <= 100; i++) { fib(i, fibCache) }
123+
console.log('Fibonacci Series Cache: ', fibCache.cacheInfo(), '\n')
124+
}
125+
126+
main()

0 commit comments

Comments
 (0)