链表&LRU

简介

链表就是链式存储数据的一种数据结构。双向链表每个数据存储都包含他的前后数据节点的位置信息(索引/指针)。

   class DSChain<T>
    {
        //使用栈来进行废弃空间回收
        private DSStack<int> _recycle;

        //数据需要三个数据来存储内容,分别存储前后节点索引和数据本身
        private int[] _prev;
        private T[] _ds;
        private int[] _next;

        //链表头尾的索引,跟踪表尾主要方便LRU使用
        private int _head;
        private int _tail;

        public DSChain(int length)
        {
            _head = -1;
            _tail = -1;
            _prev = new int[length];
            _ds = new T[length];
            _next = new int[length];

            _recycle = new DSStack<int>(length);
            //将所有可用空间压入栈,也可改良当顺序空间耗尽后再读取栈中记录的回收空间
            for (int i = 0; i < length; i++)
            {
                _recycle.Push(i);
            }
        }

        //搜索数据,返回所在索引
        int Search(T data)
        {
            if (_head == -1) return -1;
            int index = _head;
            while (!_ds[index].Equals(data))
            {
                index = _next[index];
                if (index == -1) return -1;
            }
            return index;
        }

        public bool Insert(T data)
        {
            int index;
            if (!_recycle.Pop(out index)) return false;
            if (_head == -1)
            {
                _prev[index] = -1;
                _ds[index] = data;
                _next[index] = -1;
                _tail = index;
            }
            else
            {
                _prev[index] = -1;
                _ds[index] = data;
                _next[index] = _head;
                _prev[_head] = index;
            }
            _head = index;
            return true;
        }

        public bool Delete(T data)
        {
            int index = Search(data);
            if (index == -1) return false;

            if (_prev[index] != -1) _next[_prev[index]] = _next[index];
            else _head = _next[index];

            if (_next[index] != -1) _prev[_next[index]] = _prev[index];
            else _tail = _prev[index];

            _recycle.Push(index);
            return true;
        }

        //LRU
        public bool DeleteLast()
        {
            int index = _tail;
            if (index == -1) return false;
            _tail = _prev[index];
            _next[_prev[index]] = -1;
            _recycle.Push(index);
            return true;
        }

        //LRU访问方法,读取数据的同时调整数据在链表中位置
        //链表这种数据结构实现LRU非常方便
        public bool LRUAccess(T data)
        {
            int index = Search(data);
            if (index == -1) return false;
            if (_head == index) return true;
            if (_tail == index) _tail = _prev[index];

            _next[_prev[index]] = _next[index];
            if (_next[index] != -1) _prev[_next[index]] = _prev[index];

            _prev[index] = -1;
            _next[index] = _head;
            _prev[_head] = index;
            _head = index;
            return true;
        }
    }

链表&LRU

时间: 2024-10-07 01:33:49

链表&LRU的相关文章

单链表LRU

单链表实现lru 越靠近链表尾部的节点是越早之前访问的 当有一个新的数据被访问时,从链表头开始顺序遍历链表 1.如果此数据之前已经被缓存在链表中 遍历得到这个数据对应的节点,并将其从原来的位置删除,然后再插入到链表的头部 2.没在缓存链表里 2.1 缓存未满,将次节点直接插入到链表的头部 2.2 已经满了,删除链表尾部节点,将新的数据节点插入到链表的头部 single_list_lru.c 原文地址:https://www.cnblogs.com/HKUI/p/10659965.html

Linux内核剖析 之 回收页框

一.页框回收算法 1.为何要有页框回收算法? Linux在为用户态与内核分配动态内存时,检查得并不严谨. 例如: (1).对单个用户创建的进程的RAM使用的总量并不作严格的检查(进程资源的限制只针对单个进程): (2).对内核使用的许多磁盘高速缓存和内存高速缓存大小也同样不做限制. 2.为何要减少控制? 可以使内核以最好的可行方式使用可用的RAM: (1).当系统负载较低时,RAM的大部分由磁盘高速缓存占用,较少的正在运行的进程可以获益: (2).当系统负载增加时,RAM的大部分则由进程页占用,

linux内存源码分析 - 内存回收(lru链表)

本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 概述 对于整个内存回收来说,lru链表是关键中的关键,实际上整个内存回收,做的事情就是处理lru链表的收缩,所以这篇文章就先说说系统的lru链表. 内存回收的核心思想,就是如果一些数据能够保存到磁盘,在内存不足时就把这些数据写到磁盘中,这样这些数据占用的内存页就可以作为空闲内存页给予系统使用了. 当内存不足时,系统就必须要将一些页框回收,而哪些页框可以回收呢,之前我们有说过,属于内核的大部分页框是不能够进行回

FJUTOJ-3682 LRU算法的实现2 (链表+哈希)

[FJUTOJ-3682] LRU算法的实现2 传送门 此题让我们实现一个LRU的模板类.本题较简便且高效的写法是维护一个std::list和一个std::unordered_map. std::list 与 std::unordered_map 中存放的内容 std::list中存放各key,类型为K.链表中各键码存放的顺序是按照访问顺序存放的. std::unordered_map中以key为第一维,第二维为一个pair,其first和second分别为: first: 该key对应的val

06 | 链表(上):如何实现LRU缓存淘汰算法?

我们先来讨论一个经典的链表应用场景,那就是 LRU 缓存淘汰算法. 缓存的大小有限,当缓存被用满时,哪些数据应该被清理出去,哪些数据应该被保留?这就需要缓存淘汰策略来决定. 常见的策略有三种: 先进先出策略 FIFO(First In,First Out).最少使用策略 LFU(Least Frequently Used).最近最少使用策略 LRU(Least Recently Used). 三种最常见的链表结构,它们分别是:单链表.双向链表和循环链表. 数组简单易用,在实现上使用的是连续的内存

Chapter 6 链表(上):如何实现LRU缓存淘汰算法?

缓存淘汰策略: 一.什么是链表? 1.和数组一样,链表也是一种线性表. 2.从内存结构来看,链表的内存结构是不连续的内存空间,是将一组零散的内存块串联起来,从而进行数据存储的数据结构. 3.链表中的每一个内存块被称为节点Node.节点除了存储数据外,还需记录链上下一个节点的地址,即后继指针next. 二.为什么使用链表?即链表的特点 1.插入.删除数据效率高O(1)级别(只需更改指针指向即可),随机访问效率低O(n)级别(需要从链头至链尾进行遍历). 2.和数组相比,内存空间消耗更大,因为每个存

LRU 缓冲池 (不考虑多线程)

lru:(转)LRU算法的实现 什么是LRU算法? LRU是Least Recently Used的缩写,即最近最少使用页面置换算法,是为虚拟页式存储管理服务的.关于操作系统的内存管理,如何节省利用容量不大的内存为最多的进程提供资源,一直是研究的重要方向.而内存的虚拟存储管理,是现在最通用,最成功的方式——在内存有限的情况下,扩展一部分外存作为虚拟内存,真正的内存只存储当前运行时所用得到信息.这无疑极大地扩充了内存的功能,极大地提高了计算机的并发度.虚拟页式存储管理,则是将进程所需空间划分为多个

缓存淘汰算法之LRU实现

Java中最简单的LRU算法实现,就是利用 LinkedHashMap,覆写其中的removeEldestEntry(Map.Entry)方法即可 如果你去看LinkedHashMap的源码可知,LRU算法是通过双向链表来实现,当某个位置被命中,通过调整链表的指向将该位置调整到头位置,新加入的内容直接放在链表头, 如此一来,最近被命中的内容就向链表头移动,需要替换时,链表最后的位置就是最近最少使用的位置. import java.util.ArrayList; import java.util.

146. LRU Cache

Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and put. get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1. put