码字不易,转载请附原链,搬砖繁忙回复不及时见谅,技术交流请加QQ群:909211071
数据结构:
- 双向链表作为LRU队列
- 链表尾指针降低添加和修改时间复杂度为O(1)
- HashMap存储每个元素的地址,降低修改时间复杂度为O(1)
添加、访问、删除操作:
- 添加:直接通过尾指针加到队尾,如果大于容量,删除队头节点
- 修改:通过HashMap拿到对应节点的地址,通过前后指针删除当前节点,再通过尾指针加到队尾
- 删除:通过HashMap拿到对应节点的地址,通过前后指针删除当前节点
代码:
<?php
class ListQueue
{
public $maxCount = 3;
public $head = null;
public $tail = null;
public $count = 0;
public function add($key, $value)
{
$node = new Node();
$node->key = $key;
$node->value = $value;
if ($this->head === null){
$this->head = $node;
}else{
$node->pre = $this->tail;
$this->tail->next = $node;
}
$this->tail = $node;
$this->incrCount();
return $node;
}
public function del($node)
{
$pre = $node->pre;
$next = $node->next;
if ($pre === null){
$next->pre = null;
$this->head = $next;
}else{
$pre->next = $node->next;
$next->pre = $pre;
}
$node->next = null;
$this->decrCount();
}
public function delHead()
{
$oldHead = $this->head;
$this->head = $oldHead->next;
$this->head->pre = null;
$this->decrCount();
return $oldHead->key;
}
public function incrCount()
{
$this->count++;
}
public function decrCount()
{
$this->count > 0 && $this->count--;
}
public function checkMax()
{
return $this->count > $this->maxCount;
}
}
class Node
{
public $key;
public $value;
public $pre;
public $next;
}
class Lru
{
public $list = null;
public $hashMap = [];
public function __construct()
{
$this->list = new ListQueue();
}
public function add($key, $value)
{
$node = $this->list->add($key, $value);
$this->hashMap[$key] = $node;
if ($this->list->checkMax()){
$headKey = $this->list->delHead();
unset($this->hashMap[$headKey]);
}
}
public function get($key){
$node = $this->hashMap[$key];
if (!$node){
return false;
}
$this->list->del($node);
$node = $this->list->add($key, $node->value);
$this->hashMap[$key] = $node;
return $node->value;
}
public function update($key, $value){
$node = $this->hashMap[$key];
if (!$node){
return false;
}
$this->list->del($node);
$node = $this->list->add($key, $value);
$this->hashMap[$key] = $node;
}
}
$lru = new Lru();
$lru->add('why', 'why');
$lru->add('jzm', 'jzm');
$lru->add('ymt', 'ymt');
$lru->get('jzm');
$lru->update('why', 'why111');
$lru->add('123', '123');
print_r($lru->list);
运行结果:
[why@whydeMacBook-Pro] ~/Desktop/php$php lru.php
Array
(
[why] => Node Object
(
[key] => why
[value] => why111
[pre] => Node Object
(
[key] => jzm
[value] => jzm
[pre] =>
[next] => Node Object
*RECURSION*
)
[next] => Node Object
(
[key] => 123
[value] => 123
[pre] => Node Object
*RECURSION*
[next] =>
)
)
[jzm] => Node Object
(
[key] => jzm
[value] => jzm
[pre] =>
[next] => Node Object
(
[key] => why
[value] => why111
[pre] => Node Object
*RECURSION*
[next] => Node Object
(
[key] => 123
[value] => 123
[pre] => Node Object
*RECURSION*
[next] =>
)
)
)
[123] => Node Object
(
[key] => 123
[value] => 123
[pre] => Node Object
(
[key] => why
[value] => why111
[pre] => Node Object
(
[key] => jzm
[value] => jzm
[pre] =>
[next] => Node Object
*RECURSION*
)
[next] => Node Object
*RECURSION*
)
[next] =>
)
)
ListQueue Object
(
[maxCount] => 3
[head] => Node Object
(
[key] => jzm
[value] => jzm
[pre] =>
[next] => Node Object
(
[key] => why
[value] => why111
[pre] => Node Object
*RECURSION*
[next] => Node Object
(
[key] => 123
[value] => 123
[pre] => Node Object
*RECURSION*
[next] =>
)
)
)
[tail] => Node Object
(
[key] => 123
[value] => 123
[pre] => Node Object
(
[key] => why
[value] => why111
[pre] => Node Object
(
[key] => jzm
[value] => jzm
[pre] =>
[next] => Node Object
*RECURSION*
)
[next] => Node Object
*RECURSION*
)
[next] =>
)
[count] => 3
)
[why@whydeMacBook-Pro] ~/Desktop/php$