1. LRU算法概述
LRU(最近最少使用)是一种常见的缓存淘汰算法,其基本原理是根据数据的访问时间来决定被淘汰的数据。LRU算法认为,最近被访问的数据有更高的概率在未来被再次访问,因此将较早未被访问的数据淘汰。
2. LRU算法的实现
2.1 使用数组和链表
为了实现LRU算法,我们可以使用数组和链表的结合。数组可以快速定位一个数据是否存在,而链表可以维护数据的访问顺序。
具体实现可以定义一个双向链表结构,每个节点包含数据和前后指针。同时,使用一个哈希表来存储每个数据的引用,这样可以通过哈希表快速定位数据在链表中的位置。
class LRUCache {
private $capacity;
private $cache;
private $head;
private $tail;
public function __construct($capacity) {
$this->capacity = $capacity;
$this->cache = [];
$this->head = new ListNode();
$this->tail = new ListNode();
$this->head->next = $this->tail;
$this->tail->prev = $this->head;
}
...
以上代码定义了一个LRUCache类,其中包含了容量、缓存数组、头节点和尾节点。头节点和尾节点是为了方便操作链表而引入的。
2.2 实现get和put方法
LRUCache类中还需要实现get和put方法,分别用于获取数据和插入数据。在get方法中,首先从哈希表中查找数据是否存在,如果存在,则将该节点移动到链表的头部,并返回数据。如果数据不存在,则返回-1。
在put方法中,首先从哈希表中查找数据是否存在。如果存在,则将节点移动到链表的头部,并更新数据。如果数据不存在,则插入新节点到链表的头部。如果缓存容量已满,则删除链表尾部的节点,并删除哈希表中对应的引用。最后,插入新节点到链表的头部,并更新哈希表。
...
public function get($key) {
if (isset($this->cache[$key])) {
$node = $this->cache[$key];
$this->moveToHead($node);
return $node->val;
} else {
return -1;
}
}
public function put($key, $value) {
if (isset($this->cache[$key])) {
$node = $this->cache[$key];
$node->val = $value;
$this->moveToHead($node);
} else {
$node = new ListNode($key, $value);
$this->addToHead($node);
$this->cache[$key] = $node;
if (count($this->cache) > $this->capacity) {
$removed = $this->removeTail();
unset($this->cache[$removed->key]);
}
}
}
...
以上代码中的moveToHead方法用于将节点移动到链表的头部,addToHead方法用于将节点插入到链表的头部,removeTail方法用于删除链表的尾部节点。
3. 测试LRU算法
使用以上实现的LRU算法,我们可以快速测试其效果。
以下是一个简单的测试代码:
$cache = new LRUCache(2);
$cache->put(1, 'A');
$cache->put(2, 'B');
$cache->put(3, 'C');
echo 'get(1): ' . $cache->get(1) . "\n";
echo 'get(2): ' . $cache->get(2) . "\n";
echo 'get(3): ' . $cache->get(3) . "\n";
运行以上代码,输出为:
get(1): -1
get(2): B
get(3): C
可以看到,LRU算法在缓存容量为2时,成功将最久未被访问的数据1淘汰,并保留了最新访问的数据2和3。
4. 总结
LRU算法是一种常用的缓存淘汰算法,通过记录数据的访问顺序来决定淘汰哪些数据。实现LRU算法可以使用数组和链表结合的方式,通过哈希表快速定位数据在链表中的位置。PHP提供了相关的数据结构和函数来实现LRU算法,可以根据实际情况选择合适的实现方式。