理解双向链表的优势:利用双向链表实现LRU算法

1.背景:为什么用双向链表管理LRU?为什么不用单链表?

由于LRU算法的特性,需要不断的对链表进行添加以及移位的操作(添加新入元素,移位:最近访问的元素加到链表头,最近访问的元素要移动到链表尾),所以需要维护链表的头节点以及尾节点位置,如果用单链表实现,效率非常低,因为每次要添加元素都要遍历链表找到链表尾(O(n))。所以用双向链表的优势,可以只用一个head头节点就可以用O(1)复杂度查找到链表头与链表尾的位置。

例如:(放最近访问的元素)<-----prev  head  next------>(放新添加的元素)

接下来从新建LRU链表,添加元素, 移位元素(即最近访问的元素移位)来介绍此算法

2.新建LRU链表

// 链表结构体
struct LinkNode{
    int value;
    LinkNode* prev;
    LinkNode* next;

    LinkNode(int _value = 0, LinkNode* p = nullptr, LinkNode* n = nullptr):
                value(_value), prev(p), next(n) {}
};

// 初始化头节点
LinkNode head;

head.prev = &head;
head.next = &head;

3.向LRU链表中添加元素

std::vector<int> Test{1,3,5,5,1,4,6,4,3,2,1,2,3,4,1,2,3,1,5,,5,5,5,2,1};

LinkNode* curr;
for (auto i:Test) {
    curr = new LinkNode(i);

    // 新加入的节点,全部放在head的next方向的第一个,也就是prev方向的最后一个
    // <-----prev  head  next------>
    curr->next = head.next;
    curr->prev = &head;

    head.next->prev = curr;
    head.next = curr;

}

4.对LRU链表操作,移动最近访问的元素到prev方向首位

// 需要的操作: 把curr节点放到head的prev方向的第一位

// 1.删除节点:
curr->prev->next = curr->next;
curr->next->prev = curr->prev;

// 2.插入该位置:
    // 最近访问的节点,全部放在head的prev方向的第一个,也就是next方向的最后一个
    // <-----prev  head  next------>
curr->prev = head.prev;
curr->next = &head;
head.prev->next = curr;
head.prev = curr;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值