Skip to content

Commit 6607118

Browse files
committed
implement O(1) LRU Cache with eviction policy
1 parent f13588d commit 6607118

1 file changed

Lines changed: 74 additions & 0 deletions

File tree

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
class Node:
2+
# Create a building block for the cache
3+
def __init__(self, key, value):
4+
self.key = key
5+
self.value = value
6+
self.next = None
7+
self.previous = None
8+
9+
10+
class LruCache:
11+
# Initializes the cache with a maximum capacity
12+
def __init__(self, limit):
13+
if limit <= 0:
14+
raise ValueError("Cache limit must be greater than zero.")
15+
self.limit = limit
16+
self.cache = {} # Maps key -> Node for O(1) lookups
17+
self.head = None # Most recently used
18+
self.tail = None # Least recently used
19+
20+
# Looks up a value and marks it as recently used
21+
def get(self, key):
22+
if key not in self.cache:
23+
return None
24+
25+
node = self.cache[key]
26+
self._move_to_head(node)
27+
return node.value
28+
29+
# Add or update an item, evicting the oldest if full
30+
def set(self, key, value):
31+
if key in self.cache:
32+
node = self.cache[key]
33+
node.value = value
34+
self._move_to_head(node)
35+
return
36+
37+
if len(self.cache) >= self.limit:
38+
if self.tail is not None:
39+
del self.cache[self.tail.key]
40+
41+
if self.head == self.tail:
42+
self.head = None
43+
self.tail = None
44+
else:
45+
self.tail = self.tail.previous
46+
self.tail.next = None
47+
48+
new_node = Node(key, value)
49+
self.cache[key] = new_node
50+
51+
if self.head is None:
52+
self.head = new_node
53+
self.tail = new_node
54+
else:
55+
new_node.next = self.head
56+
self.head.previous = new_node
57+
self.head = new_node
58+
59+
# Internal helper to reposition a used node to the front
60+
def _move_to_head(self, node):
61+
if self.head == node:
62+
return
63+
64+
if node == self.tail:
65+
self.tail = node.previous
66+
self.tail.next = None
67+
else:
68+
node.previous.next = node.next
69+
node.next.previous = node.previous
70+
71+
node.next = self.head
72+
self.head.previous = node
73+
node.previous = None
74+
self.head = node

0 commit comments

Comments
 (0)