HashMap+双向链表,看完之后,再也不怕头条面试官让我手撕LRU算法了

码字不易,转载请附原链,搬砖繁忙回复不及时见谅,技术交流请加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$

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AirGo.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值