Skip to content

Commit 106bf5f

Browse files
committed
feat: Implement LRU Cache algorithm
1 parent 788d95b commit 106bf5f

File tree

1 file changed

+72
-0
lines changed

1 file changed

+72
-0
lines changed

data_structures/lru_cache.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
"""
2+
An implementation of a Least Recently Used (LRU) Cache.
3+
... (the rest of the docstring is the same)
4+
"""
5+
from __future__ import annotations
6+
from typing import Optional
7+
8+
class Node:
9+
"""A node in the doubly linked list."""
10+
def __init__(self, key: int, val: int) -> None:
11+
self.key, self.val = key, val
12+
self.prev: Optional[Node] = None
13+
self.next: Optional[Node] = None
14+
15+
class LRUCache:
16+
"""
17+
A Least Recently Used (LRU) Cache data structure.
18+
... (the doctests are the same)
19+
"""
20+
def __init__(self, capacity: int) -> None:
21+
if capacity <= 0:
22+
raise ValueError("Capacity must be a positive integer.")
23+
self.capacity = capacity
24+
self.cache: dict[int, Node] = {} # Maps key to node
25+
26+
self.head = Node(-1, -1)
27+
self.tail = Node(-1, -1)
28+
self.head.next = self.tail
29+
self.tail.prev = self.head
30+
31+
def _remove(self, node: Node) -> None:
32+
"""Helper to remove a node from the list."""
33+
if node.prev and node.next:
34+
prev, nxt = node.prev, node.next
35+
prev.next = nxt
36+
nxt.prev = prev
37+
38+
def _add(self, node: Node) -> None:
39+
"""Helper to add a node to the front of the list (most recent)."""
40+
if self.head.next:
41+
node.prev = self.head
42+
node.next = self.head.next
43+
self.head.next.prev = node
44+
self.head.next = node
45+
46+
def get(self, key: int) -> int:
47+
if key in self.cache:
48+
node = self.cache[key]
49+
self._remove(node)
50+
self._add(node)
51+
return node.val
52+
return -1
53+
54+
def put(self, key: int, value: int) -> None:
55+
if key in self.cache:
56+
node = self.cache[key]
57+
node.val = value
58+
self._remove(node)
59+
self._add(node)
60+
else:
61+
new_node = Node(key, value)
62+
self.cache[key] = new_node
63+
self._add(new_node)
64+
65+
if len(self.cache) > self.capacity and self.tail.prev:
66+
lru = self.tail.prev
67+
self._remove(lru)
68+
del self.cache[lru.key]
69+
70+
if __name__ == "__main__":
71+
import doctest
72+
doctest.testmod()

0 commit comments

Comments
 (0)