11class Node :
2+ """Represents a node in the doubly-linked list."""
23 def __init__ (self , key , value ):
34 self .key = key
45 self .value = value
56 self .next = None
67 self .previous = None
78
89
9- class LruCache :
10- def __init__ (self , limit ):
11- if limit <= 0 :
12- raise ValueError ("Cache limit must be greater than 0" )
13-
14- self .limit = limit
15- self .cache = {}
16- self .head = None
17- self .tail = None
10+ class DoublyLinkedList :
11+ """Manages insertion, removal, and reordering of nodes in a doubly-linked list."""
12+ def __init__ (self ):
13+ self .head = None
14+ self .tail = None
1815
19- def get (self , key ):
20- if key not in self .cache :
21- return None
22-
23- node = self .cache [key ]
24-
25- self ._move_to_head (node )
16+ def add_to_head (self , node ):
17+ """Add a node to the head of the list."""
18+ node .next = None
19+ node .previous = None
2620
27- return node .value
28-
29- def set (self , key , value ):
30- if key in self .cache :
31- node = self .cache [key ]
32- node .value = value
33- self ._move_to_head (node )
21+ if self .head is None :
22+ self .head = node
23+ self .tail = node
3424 else :
35- if len (self .cache ) >= self .limit :
36- self ._evict_tail ()
37-
38- new_node = Node (key , value )
39- self .cache [key ] = new_node
40- self ._add_to_head (new_node )
25+ node .next = self .head
26+ self .head .previous = node
27+ self .head = node
4128
42- def _move_to_head (self , node ):
29+ def move_to_head (self , node ):
30+ """Move an existing node to the head of the list."""
4331 if node == self .head :
4432 return
4533
46- self ._remove_node (node )
47-
48- self ._add_to_head (node )
34+ self .remove_node (node )
35+ self .add_to_head (node )
4936
50- def _remove_node (self , node ):
37+ def remove_node (self , node ):
38+ """Remove a node from the list."""
5139 if node == self .head == self .tail :
5240 self .head = None
5341 self .tail = None
@@ -64,27 +52,48 @@ def _remove_node(self, node):
6452 node .next = None
6553 node .previous = None
6654
67- def _add_to_head (self , node ):
68- node .next = None
69- node .previous = None
55+ def get_tail (self ):
56+ """Return the tail node (least recently used)."""
57+ return self .tail
58+
59+
60+ class LruCache :
61+ """Implements an LRU cache with O(1) operations."""
62+ def __init__ (self , limit ):
63+ if limit <= 0 :
64+ raise ValueError ("Cache limit must be greater than 0" )
7065
71- if self .head is None :
72- self .head = node
73- self .tail = node
74- else :
75- node .next = self .head
76- self .head .previous = node
77- self .head = node
66+ self .limit = limit
67+ self .cache = {}
68+ self .order = DoublyLinkedList ()
7869
79- def _evict_tail (self ):
80- if self .tail is None :
81- return
70+ def get (self , key ):
71+ """Retrieve a value and mark it as recently used."""
72+ if key not in self .cache :
73+ return None
8274
83- del self .cache [self .tail .key ]
75+ node = self .cache [key ]
76+ self .order .move_to_head (node )
8477
85- if self .head == self .tail :
86- self .head = None
87- self .tail = None
78+ return node .value
79+
80+ def set (self , key , value ):
81+ """Store a key-value pair and evict LRU if necessary."""
82+ if key in self .cache :
83+ node = self .cache [key ]
84+ node .value = value
85+ self .order .move_to_head (node )
8886 else :
89- self .tail = self .tail .previous
90- self .tail .next = None
87+ if len (self .cache ) >= self .limit :
88+ self ._evict_lru ()
89+
90+ new_node = Node (key , value )
91+ self .cache [key ] = new_node
92+ self .order .add_to_head (new_node )
93+
94+ def _evict_lru (self ):
95+ """Remove the least recently used item."""
96+ lru_node = self .order .get_tail ()
97+ if lru_node is not None :
98+ del self .cache [lru_node .key ]
99+ self .order .remove_node (lru_node )
0 commit comments