栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

双链表实现LRU算法

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

双链表实现LRU算法

链表

所谓链表就是一个节点指向另一个节点的数据结构,像一条链子把每个节点连接起来。
如果一个节点既指向了后面的节点,也指向了前面的节点,这些节点就构成了双向链表。
我们先定义这个节点结构

class NodeLRU
{
public:
    NodeLRU(int v) : val(v), prev(nullptr), next(nullptr) {}

    int val;
    NodeLRU *prev;
    NodeLRU *next;
};

val为节点的数据域表示节点存储的数值
prev为节点的前一个节点
next为节点的后一个节点
然后我们把这些节点串连起来,定义一个链表的结构

一个双向链表的结构图

现在我们实现LRU算法:
1 插入一个节点数据域为val,如果链表中有和val匹配的节点,则将该节点移动到链表头,如果没有该节点则直接插入头部。
2 在执行1操作时,如果链表长度已经达到最大,则删除尾节点,在头部插入。

接下来我们实现LRU类,通过插入节点实现LRU算法。

class LRU
{
public:
    LRU(int sz) : max_size(sz), cur_size(0), head(nullptr), tail(nullptr) {}
    LRU() = default;
    void insert(int val)
    {
        if (max_size == 0)
        {
            return;
        }

        if (head == tail && head == nullptr)
        {
            auto node = new NodeLRU(val);
            head = node;
            tail = node;
            cur_size++;
            return;
        }

        auto node_find = find(val);
        if (node_find == nullptr)
        {
            //节点数量达到上限
            if (cur_size >= max_size)
            {
                //删除尾节点
                auto deltail = tail;
                if (tail->prev != nullptr)
                {
                    tail->prev->next = nullptr;
                }

                tail = tail->prev;
                delete (deltail);
                cur_size--;
            }

            //插入头部节点
            auto node = new NodeLRU(val);
            node->next = head;
            head->prev = node;
            head = node;
            cur_size++;
            return;
        }

        //头部节点就不处理
        if (node_find == head)
        {
            return;
        }

        //如果是尾部节点
        if (node_find == tail)
        {
            node_find->prev->next = nullptr;
            tail = node_find->prev;
        }
        else
        {
            //先将node_find节点前后节点连接起来
            node_find->prev->next = node_find->next;
            node_find->next->prev = node_find->prev;
        }

        //在将node_find节点插入头部
        node_find->prev = nullptr;
        node_find->next = head;
        head = node_find;
    }

    NodeLRU *find(int sz)
    {
        auto node = head;
        while (node != nullptr)
        {
            if (node->val == sz)
            {
                return node;
            }
            node = node->next;
        }

        return nullptr;
    }

    void print()
    {
        for (auto node = head; node != nullptr; node = node->next)
        {
            cout << node->val << " -> ";
        }

        cout << "null" << endl;
    }

    ~LRU()
    {
        for (auto node = head; node != nullptr;)
        {
            auto nodedel = node;
            node = node->next;
            delete (nodedel);
        }
        head = nullptr;
        tail = nullptr;
    }

private:
    NodeLRU *head;
    NodeLRU *tail;
    int max_size;
    int cur_size;
};

max_size 表示链表最大长度,cur_size表示链表当前长度,head表示链表的头结点,tail表示链表的尾节点。

接下来我们测试LRU类

    auto lru = LRU(3);
    lru.insert(4);
    lru.insert(3);
    lru.insert(2);
    lru.print();
    lru.insert(100);
    lru.print();
    lru.insert(10);
    lru.print();

程序输出

2 -> 3 -> 4 -> null
100 -> 2 -> 3 -> null
10 -> 100 -> 2 -> null

源码链接https://gitee.com/secondtonone1/algorithms
我的公众号,谢谢关注

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/687131.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号