引言
LRU(最近最少使用算法):是最近最少使用的页面置换算法,选择最近最久未使用的页面予以淘汰。该算法是常见的页面置换算法,该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间t,当要淘汰一个页面时,选择现有页面中t最大的。
举例说明
LRU算法是针对内存不足时将最远最久未使用的踢出内存中,如该例中一开始7,0,1,内存中并没有所以就全部进入内存中,然后内存满的时候,有一个2,由于7是最远未使用的,所以2替代7的位置,然后又有一个0出现,由于这个里面有一个0,所以0自己更新为最近的已使用的,后面有个3,由于0已经被使用过了,所以3就取代最久未被使用的2。
题目中体现
相信大家看了上面的例子,已经对LRU算法有一定的了解,接下来就直接咋题目中体现。
这个是我今天刷到的一道题目,一开始看到这道题就先复习了一个LRU的基本特点。接下来看这道题目的一种解法。
class Node:
_slots_ = 'prev', 'next', 'key','value'
def __init__(self, key=0, value=0):
self.key = key
self.value = value
class LRUCache:
def __init__(self, capacity: int):
self.capacity = capacity
self.dummy = Node()
self.dummy.prev = self.dummy
self.dummy.next = self.dummy
self.key_to_node = dict()
def get_node(self, key: int) -> Optional[Node]:
if key not in self.key_to_node:
return None
node = self.key_to_node[key]
self.remove(node)
self.push_front(node)
return node
def get(self, key:int) -> int:
node = self.get_node(key)
return node.value if node else -1
def put(self, key: int, value: int) -> None:
node = self.get_node(key)
if node:
node.value = value
return
self.key_to_node[key] = node = Node(key, value)
self.push_front(node)
if len(self.key_to_node) > self.capacity:
back_node = self.dummy.prev
del self.key_to_node[back_node.key]
self.remove(back_node)
def remove(self, x:Node) -> None:
x.prev.next = x.next
x.next.prev = x.prev
def push_front(self, x:Node) -> None:
x.prev = self.dummy
x.next = self.dummy.next
x.prev.next = x
x.next.prev = x
# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)
这道题利用了链表中最基本的性质,即一开始就在链表中给出四个值'prev', 'next', 'key','value',即链表的前节点,后节点,值相对应的指针。然后确定该链表中的最大容量,这是第一步,将所有该准备好的全部准备好。第二步,将哈希表引入进来,因为哈希表查找效率高,首先查看键是否存在于哈希表中,因为python中的字典就是哈希表,所以要确保可以使用哈希表。然后就是从哈希表中获取节点,将节点从链表中脱离出来,移动到头部。get这个函数主要是获取新的节点(对应内存中获取新的数),然后remove函数是移除节点(对应淘汰最久未使用的数)。这里面最主要的是put函数,因为put是在get函数获取新的节点之后,进行判断,如果小于最大容量,则可以继续,如果大于最大容量就需要根据最近最久来进行抉择。最后push_front函数是将节点插入双向链表中,来表示是最近访问的节点,这样五步就可以将LRU算法利用哈希表和双向链表实现