计算机基础:21、计算机基础实践-双向链表数据结构、FIFO算法、LRU算法
单向链表与双向链表的简介
双向链表数据结构
下方的代码实现了上图中的功能(双向链表数据结构)
# node类表示在链表中的节点
class Node:
def __init__(self, key, value):
self.key = key
self.value = value
self.prev = None # 用于存储上一个节点
self.next = None # 用于存储下一个节点
def __str__(self):
val = '{%d: %d}' % (self.key, self.value)
return val
def __repr__(self):
val = '{%d: %d}' % (self.key, self.value)
return val
# 双向链表
class DoubleLinkedList:
def __init__(self, capacity=0xffff):
self.capacity = capacity
self.head = None # 链表头部节点
self.tail = None # 链表尾部节点
self.size = 0 # 链表长度
# 从头部添加节点
def __add_head(self, node):
if not self.head:
# 当前链表中没有节点
self.head = node
self.tail = node
self.head.next = None
self.head.prev = None
else:
# 当前链表中有节点
node.next = self.head
self.head.prev = node
self.head = node
self.head.prev = None
self.size += 1
return node
# 从尾部添加节点
def __add_tail(self, node):
if not self.tail:
self.tail = node
self.head = node
self.tail.next = None
self.tail.prev = None
else:
self.tail.next = node
node.prev = self.tail
self.tail = node
self.tail.next = None
self.size += 1
return node
# 从尾部删除
def __del_tail(self):
if not self.tail:
return
node = self.tail
if node.prev:
self.tail = node.prev
self.tail.next = None
else:
self.tail = self.head = None
self.size -= 1
return node
# 从头部删除
def __del_head(self):
if not self.head:
return
node = self.head
if node.next:
self.head = node.next
self.head.prev = None
else:
self.tail = self.head = None
self.size -= 1
return node
# 任意节点删除
def __remove(self, node):
# 如果node=None,默认删除尾部节点
if not node:
node = self.tail
if node == self.tail:
self.__del_tail()
elif node == self.head:
self.__del_head()
else:
node.prev.next = node.next
node.next.prev = node.prev
self.size -= 1
return node
# 弹出头部节点
def pop(self):
return self.__del_head()
# 添加节点,默认往尾部添加
def append(self, node):
return self.__add_tail(node)
# 往头部添加节点
def append_front(self, node):
return self.__add_head(node)
# 删除节点(node为空则默认删除最后一个节点,否则删除指定节点)
def remove(self, node=None):
return self.__remove(node)
# 打印当前链表
def print(self):
p = self.head
line = ''
while p:
line += '%s' % p
p = p.next
if p:
line += '=>'
print(line)
if __name__ == '__main__':
l = DoubleLinkedList(10)
noees = []
for i in range(10):
node = Node(i, i)
nodes.append(node)
l.append(nodes[0])
l.print()
l.append(nodes[1])
l.print()
l.pop()
l.print()
l.append(nodes[2])
l.print()
l.append_front(nodes[3])
l.print()
l.append(nodes[4])
l.print()
l.remove(nodes[2])
l.print()
l.remove()
l.print()
FIFO缓存置换算法(先进先出算法)
FIFO缓存置换算法,当需要淘汰缓存的时候,把最先进入链表的节点淘汰
class FIFOCache(object):
def __init__(self,capacity):
self.capacity = capacity
self.size = 0
self.map = {}
self.list = DoubleLinkedList(self.capacity)
# 获取缓存
def get(self, key):
if key not in self.map:
return -1
else:
node = self.map.get(key)
return node.value
# 写入缓存
def put(self, key, value):
if self.capacity == 0:
return
if key in self.map:
node = self.map.get(key)
self.list.remove(node)
node.value = value
self.list.append(node)
else:
if self.size == self.capacity
node = self.list.pop()
del self.map[node.key]
self.size -= 1
node = Node(key, value)
self.list.append(node)
self.map[key] = node
self.size += 1
def print(self):
self.list.print()
if __name__ == '__main__':
cache = FIFOCache(2)
cache.put(1, 1)
cache.print()
cache.put(2, 2)
cache.print()
print(cache.get(1))
cache.put(3,3)
cache.print()
print(cache.get(2))
cache.print()
cache.put(4,4)
cache.print()
print(cache.get(1))
最近最少使用算法(LRU)
每次使用缓存的时候,把使用的缓存移到链表的最前面,需要淘汰的时候直接把链表尾部的节点淘汰即可
class LRUCache(object):
def __init__(self, capacity):
self.capacity = capacity
self.map = {}
self.list = DoubleLinkedList(self.capacity)
def get(self, key):
if key in self.map:
node = self.map[key]
self.list.remove(node)
self.list.append_front(node)
return node.value
else:
return -1
def put(self, key, value):
if key in self.map:
node = self.map.get(key)
self.list.remove(node)
node.value = value
self.list.append_front(node)
else:
node = Node(key,value)
#缓存已满
if self.list.size >= self.list.capacity:
old_node = self.list.remove()
self.map.pop(old_node.key)
#缓存未满
self.list.append_front(node)
self.map[key] = node
def print(self):
self.list.print()
if __name__ == '__main__':
cache = LRUCache(2)
cache.put(2, 2)
cache.print()
cache.put(1,1)
cache.print()
cache.put(3,3)
cache.print()
print(cache.get(1))
cache.print()
print(cache.get(2))
cache.print()
print(cache.get(3))
cache.print()