Skip to content

Instantly share code, notes, and snippets.

@ausaki
Last active January 21, 2019 08:21
Show Gist options
  • Select an option

  • Save ausaki/6ca24773d4cb93a02b454f6a200ae0e2 to your computer and use it in GitHub Desktop.

Select an option

Save ausaki/6ca24773d4cb93a02b454f6a200ae0e2 to your computer and use it in GitHub Desktop.
# -*- coding: utf8 -*-
"""
source:https://github.com/donnemartin/system-design-primer/blob/master/solutions/object_oriented_design/lru_cache/lru_cache.ipynb
"""
class Node(object):
def __init__(self, key, val):
self.key = key
self.val = val
self.prev = None
self.next = None
class LinkedQueue(object):
"""
双向链表实现的队列
"""
def __init__(self):
self.size = 0
self.head = None
self.tail = None
def _empty(self):
return self.size == 0
def __str__(self):
if self._empty():
return 'Queue([])'
h = self.head
s = []
while h:
s.append('[{}:{}]'.format(h.key, h.val))
h = h.next
return 'Queue({})'.format(' <-> '.join(s))
def append(self, node):
if self._empty():
node.prev = node.next = None
self.head = self.tail = node
else:
self.tail.next = node
node.prev = self.tail
node.next = None
self.tail = node
self.size += 1
def pop(self):
if self._empty():
return None
node = self.head
next_node = node.next
node.next = node.prev = None
if next_node:
next_node.prev = None
self.head = next_node
self.size -= 1
if self._empty():
self.head = self.tail = None
return node
def move_to_tail(self, node):
if self._empty():
return
if node == self.tail:
# if node is head, then no need to move it.
return
if node == self.head:
self.pop()
else:
node.prev.next = node.next
node.next.prev = node.prev
self.size -= 1
self.append(node)
class LRUCache(object):
"""LRUCache
"""
def __init__(self, capacity):
"""
:type capacity: int
"""
self.capacity = capacity
self.size = 0
self.cache = dict()
self.queue = LinkedQueue()
def full(self):
return self.size == self.capacity
def empty(self):
return self.size == 0
def remove_old(self):
old_node = self.queue.pop()
self.cache.pop(old_node.key)
self.size -= 1
def get(self, key):
"""
:type key: int
:rtype: int
"""
node = self.cache.get(key)
if node is None:
return -1
val = node.val
self.queue.move_to_tail(node)
return val
def put(self, key, value):
"""
:type key: int
:type value: int
:rtype: void
"""
if key in self.cache:
node = self.cache[key]
node.val = value
self.queue.move_to_tail(node)
return
if self.full():
self.remove_old()
node = Node(key, value)
self.queue.append(node)
self.cache[key] = node
self.size += 1
# test case
operations = ["LRUCache","put","put","get","put","put","get"]
args = [[2],[2,1],[2,2],[2],[1,1],[4,1],[2]]
cache = None
for op, arg in zip(operations, args):
print(op, arg)
if op == 'LRUCache':
cache = LRUCache(*arg)
else:
v = getattr(cache, op)(*arg)
if op == 'get':
print('get:', v)
print('queue:', cache.queue)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment