Skip to content

Commit 5187058

Browse files
authored
LRUCache
Implement with hash and double linked list
1 parent 2fdca2e commit 5187058

File tree

1 file changed

+107
-0
lines changed

1 file changed

+107
-0
lines changed

python/06_linkedlist/LRUCache.py

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# Definition for singly-linked list.
2+
class DbListNode(object):
3+
def __init__(self, x, y):
4+
self.key = x
5+
self.val = y
6+
self.next = None
7+
self.prev = None
8+
9+
10+
class LRUCache:
11+
'''
12+
leet code: 146
13+
运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。
14+
它应该支持以下操作: 获取数据 get 和 写入数据 put 。
15+
获取数据 get(key) - 如果密钥 (key) 存在于缓存中,则获取密钥的值(总是正数),否则返回 -1。
16+
写入数据 put(key, value) - 如果密钥不存在,则写入其数据值。
17+
当缓存容量达到上限时,它应该在写入新数据之前删除最近最少使用的数据值,从而为新的数据值留出空间
18+
19+
哈希表+双向链表
20+
哈希表: 查询 O(1)
21+
双向链表: 有序, 增删操作 O(1)
22+
23+
Author: Ben
24+
'''
25+
26+
def __init__(self, capacity: int):
27+
self.cap = capacity
28+
self.hkeys = {}
29+
# self.top和self.tail作为哨兵节点, 避免越界
30+
self.top = DbListNode(None, -1)
31+
self.tail = DbListNode(None, -1)
32+
self.top.next = self.tail
33+
self.tail.prev = self.top
34+
35+
def get(self, key: int) -> int:
36+
37+
if key in self.hkeys.keys():
38+
# 更新结点顺序
39+
cur = self.hkeys[key]
40+
# 跳出原位置
41+
cur.next.prev = cur.prev
42+
cur.prev.next = cur.next
43+
# 最近用过的置于链表首部
44+
top_node = self.top.next
45+
self.top.next = cur
46+
cur.prev = self.top
47+
cur.next = top_node
48+
top_node.prev = cur
49+
50+
return self.hkeys[key].val
51+
return -1
52+
53+
def put(self, key: int, value: int) -> None:
54+
if key in self.hkeys.keys():
55+
cur = self.hkeys[key]
56+
cur.val = value
57+
# 跳出原位置
58+
cur.prev.next = cur.next
59+
cur.next.prev = cur.prev
60+
61+
# 最近用过的置于链表首部
62+
top_node = self.top.next
63+
self.top.next = cur
64+
cur.prev = self.top
65+
cur.next = top_node
66+
top_node.prev = cur
67+
else:
68+
# 增加新结点至首部
69+
cur = DbListNode(key, value)
70+
self.hkeys[key] = cur
71+
# 最近用过的置于链表首部
72+
top_node = self.top.next
73+
self.top.next = cur
74+
cur.prev = self.top
75+
cur.next = top_node
76+
top_node.prev = cur
77+
if len(self.hkeys.keys()) > self.cap:
78+
self.hkeys.pop(self.tail.prev.key)
79+
# 去掉原尾结点
80+
self.tail.prev.prev.next = self.tail
81+
self.tail.prev = self.tail.prev.prev
82+
83+
def __repr__(self):
84+
vals = []
85+
p = self.top.next
86+
while p.next:
87+
vals.append(str(p.val))
88+
p = p.next
89+
return '->'.join(vals)
90+
91+
92+
if __name__ == '__main__':
93+
cache = LRUCache(2)
94+
cache.put(1, 1)
95+
cache.put(2, 2)
96+
print(cache)
97+
cache.get(1) # 返回 1
98+
cache.put(3, 3) # 该操作会使得密钥 2 作废
99+
print(cache)
100+
cache.get(2) # 返回 -1 (未找到)
101+
cache.put(4, 4) # 该操作会使得密钥 1 作废
102+
print(cache)
103+
cache.get(1) # 返回 -1 (未找到)
104+
cache.get(3) # 返回 3
105+
print(cache)
106+
cache.get(4) # 返回 4
107+
print(cache)

0 commit comments

Comments
 (0)