Skip to content

Commit ab69cdb

Browse files
committed
implemented lru_cache
1 parent cf9e042 commit ab69cdb

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
class _Node:
2+
def __init__(self, key, value):
3+
self.key = key
4+
self.value = value
5+
self.next = None
6+
self.previous = None
7+
8+
9+
class LruCache:
10+
def __init__(self, limit):
11+
if limit <= 0:
12+
raise ValueError("limit must be positive")
13+
14+
self.limit = limit
15+
self.map = {} # key -> _Node
16+
self.head = None # most recently used
17+
self.tail = None # least recently used
18+
19+
# ---- internal helpers for the linked list ----
20+
21+
def _add_to_head(self, node):
22+
"""Put node at the front (most recently used)."""
23+
node.previous = None
24+
node.next = self.head
25+
26+
if self.head is not None:
27+
self.head.previous = node
28+
self.head = node
29+
30+
if self.tail is None:
31+
# First node in the list
32+
self.tail = node
33+
34+
def _remove_node(self, node):
35+
"""Detach node from the linked list."""
36+
prev = node.previous
37+
nxt = node.next
38+
39+
if prev is not None:
40+
prev.next = nxt
41+
else:
42+
# node was head
43+
self.head = nxt
44+
45+
if nxt is not None:
46+
nxt.previous = prev
47+
else:
48+
# node was tail
49+
self.tail = prev
50+
51+
node.next = None
52+
node.previous = None
53+
54+
def _move_to_head(self, node):
55+
"""Mark node as most recently used."""
56+
if node is self.head:
57+
return
58+
self._remove_node(node)
59+
self._add_to_head(node)
60+
61+
# ---- public API ----
62+
63+
def get(self, key):
64+
node = self.map.get(key)
65+
if node is None:
66+
return None
67+
68+
# mark as recently used
69+
self._move_to_head(node)
70+
return node.value
71+
72+
def set(self, key, value):
73+
node = self.map.get(key)
74+
75+
if node is not None:
76+
# update existing
77+
node.value = value
78+
self._move_to_head(node)
79+
return
80+
81+
# new key
82+
if len(self.map) >= self.limit:
83+
# evict least recently used (tail)
84+
lru = self.tail
85+
if lru is not None:
86+
self._remove_node(lru)
87+
del self.map[lru.key]
88+
89+
new_node = _Node(key, value)
90+
self._add_to_head(new_node)
91+
self.map[key] = new_node

0 commit comments

Comments
 (0)