|
1 | 1 | from typing import Optional |
2 | 2 |
|
3 | 3 | class _Node: |
| 4 | + |
4 | 5 | def __init__(self, key=None, value=None): |
5 | | - self.key = key |
| 6 | + self.key = key |
6 | 7 | self.value = value |
7 | 8 | self.prev: Optional["_Node"] = None |
8 | 9 | self.next: Optional["_Node"] = None |
9 | | - |
10 | | -class LruCache: |
11 | | - def __init__(self, limit): |
12 | | - if limit <= 0: |
13 | | - raise ValueError("limit must be positive") |
14 | | - |
15 | | - self.limit = limit |
16 | | - self.cache = {} |
17 | | - |
| 10 | + |
| 11 | +class DoublyLinkedList: |
| 12 | + |
| 13 | + def __init__(self): |
18 | 14 | self.head = _Node() |
19 | 15 | self.tail = _Node() |
20 | 16 | self.head.next = self.tail |
21 | 17 | self.tail.prev = self.head |
22 | 18 |
|
23 | | - def remove(self, node): |
| 19 | + def remove(self, node: _Node): |
| 20 | + assert node.prev is not None |
| 21 | + assert node.next is not None |
24 | 22 | node.prev.next = node.next |
25 | 23 | node.next.prev = node.prev |
26 | 24 |
|
27 | | - def add_to_front(self, node): |
| 25 | + def add_to_front(self, node: _Node): |
28 | 26 | next_node = self.head.next |
29 | 27 | assert next_node is not None |
30 | | - |
31 | 28 | node.next = next_node |
32 | 29 | node.prev = self.head |
33 | 30 | next_node.prev = node |
34 | 31 | self.head.next = node |
35 | 32 |
|
| 33 | + def remove_last(self) -> _Node: |
| 34 | + lru = self.tail.prev |
| 35 | + assert lru is not None |
| 36 | + self.remove(lru) |
| 37 | + return lru |
| 38 | + |
| 39 | + |
| 40 | +class LruCache: |
| 41 | + |
| 42 | + def __init__(self, limit): |
| 43 | + if limit <= 0: |
| 44 | + raise ValueError("limit must be positive") |
| 45 | + |
| 46 | + self.limit = limit |
| 47 | + self.cache = {} |
| 48 | + self.list = DoublyLinkedList() |
| 49 | + |
36 | 50 | def get(self, key): |
37 | 51 | if key not in self.cache: |
38 | 52 | return None |
39 | | - |
| 53 | + |
40 | 54 | node = self.cache[key] |
41 | | - self.remove(node) |
42 | | - self.add_to_front(node) |
| 55 | + self.list.remove(node) |
| 56 | + self.list.add_to_front(node) |
43 | 57 | return node.value |
44 | 58 |
|
45 | 59 | def set(self, key, value): |
46 | 60 | if key in self.cache: |
47 | 61 | node = self.cache[key] |
48 | 62 | node.value = value |
49 | | - self.remove(node) |
50 | | - self.add_to_front(node) |
| 63 | + self.list.remove(node) |
| 64 | + self.list.add_to_front(node) |
51 | 65 | return |
52 | 66 |
|
53 | 67 | node = _Node(key, value) |
54 | 68 | self.cache[key] = node |
55 | | - self.add_to_front(node) |
| 69 | + self.list.add_to_front(node) |
56 | 70 |
|
57 | 71 | if len(self.cache) > self.limit: |
58 | | - lru = self.tail.prev |
59 | | - assert lru is not None |
60 | | - self.remove(lru) |
| 72 | + lru = self.list.remove_last() |
61 | 73 | del self.cache[lru.key] |
0 commit comments