LRU(Least recently used:最近最少使用)和LFU(Least frequently used:最不经常使用),两个都是以链表结构为基础,一般是作为缓存使用,当然,既然是缓存,空间肯定是有限制的,不然你直接把内存挤爆了,那程序也只能GG了。
在空间大小一定的情况下,LRU是淘汰最久没有使用的数据,LUF是淘汰使用次数最少的数据。
我们先来看下LRU,目的淘汰最长时间没有使用的数据对象,那么,必然是要有个排列顺序,不然如何知道那个数据最长时间没有使用?
好了,现在我们有一串数据需要按照某种顺序存储,当然,这个数据肯定是会频繁变更的,你问为啥?
缓存是干啥的?就是方便读取数据,可这个数据每次读取的肯定不会都一样啊,最终空间是肯定不够的,最终不还是要删除+修改?这也是LRU的意义所在,不然全部缓存了,还要LRU干啥子!
我们再来看看,LRU最终的期望是什么样的,不是有结果导向论么?咱就根据目标来设计结构呗!下面是一个简单的LRU的读取过程。
如上图,数据原本是A>B>C>D>E>F>G>H,如今读取到了D,那么就把D移动到最前面,变成了D>A>B>C>E>F>G>H。
如果再加上一个数据呢?比如M,那M自然也就排队在头部,尾部的数据淘汰,新的缓存就变成了M>A>B>C>E>F>G。
H由于处在最尾部,超过了空间的限制,因而被删除掉了。
这也就是我们所期望的简单的LRU实现的功能,那么根据这种情况,使用哪种结构合适呢?从上面的过程可以看到,这个list有增删,而且新增或者移动几乎都是头插法。
ArrayList直接干掉!不然移动数组元素就能把人累个半死!
接着就是链表结构了,单链表还是双链表?肯定是双链表啊,中间的数据不是有移动?没有后退指针,如何查询这个数据前面的一个?从头开始再找一遍?
大致结构固定了,来看下这个双链表的增删改查。
增:头插法,判断链表长度,插入到头结点,过载的话删除最后一个节点
改:长度不变,删除中间的某个节点,插入到头部,两步完成。
查:从头结点开始,查询对应数据,时间复杂度O(n)。
LRU结构追求的就是速度,利用内存来置换时间,减轻数据库端负载,而且查询的次数非常多,无论是查询还是改动的时候定位数据,都会用到。O(n)的时间复杂度能否优化?
我们常见的时间复杂度比O(n)还优秀的,应该就是O(logN)和O(1)了,结构有哪些呢?首先是树结构或者是跳跃表结构,查询的时间复杂度是O(logN)。不过在修改和删除的时候,涉及到树的变换和跳跃表结构的变化。可选,加上这个结构的话,如果查询次数远大于增改次数的话,时间方面应该有不小的优势。可备选。
然后就是数组,根据位置,定位对象,时间复杂的O(1),当然这个不太符合我们的要求,每次插入头部这个,就直接拖后腿了;如果根据对象信息挨个查询,时间复杂度也是O(1),那完全没必要了,这个在选择结构的时候就淘汰了,再加一个不是自找麻烦浪费时间吗?
然后就是hash,时间复杂度O(1),根据key,定位value!这个就比较符合我们的期望了了,唯一绑定,复杂度只是O(1),增删也比较方便,而且排序我们已经在双链表中做了,定位这里也就不用再关心了。
因此,LRU的结构我们便能简单的确定了,双链表+Hash,hash定位数据,双链条淘汰数据,以空间换取时间,在查询量比较大的组件中实用比较多。当然,除了双链表+hash的LRU,结构还可以进一步优化,有兴趣的可以看下Mysql的buffer pool里面的LRU list,其中一些优化就十分优秀。
代码实现什么的就不在这里赘述了,有兴趣的可以自己写一个,刚入门数据结构的话,也阔以去B站找个视频看下,最多一二十分钟,直接给你把代码写的明明白白。
说完LRU,接着就是LFU了,当然,这个也是多个结构共同组成的,hash定位肯定必不可少,这个是辅助定位数据,关系到数据的查询效率!
然后就是淘汰策略了,Least frequently used:最不经常使用,也就是说使用次数最少的,率先淘汰掉!
so,必须要有个记录使用次数的。
使用次数有 1,2,3,4...等等等,然后每个使用次数后面对应着一批数据,可能是单个,也可能多个,当然我们肯定统一认为有多个,也就是一个list!
这不就是个Map结构吗?次数是可key,数据list是value!
数据每查询一次,就将这个次数里面list的对应数据移出来,添加到当前次数+1 的Map中的value里面去!
就是加了一层,多了一个套路。
至于map中的list,直接使用双链表就好,毕竟定位的时候使用hash,新增删除双链表的速率肯定是高于数组的。
这样,LFU的结构就可以得出来了。
hash + Map (n->双链表)!
结构大致就是这样,图形什么的就不画了,绝不是因为懒,绝不是!
觉得get到一点点东东的话,帮忙点个赞呗!
来碗鸡汤: 勤学如春起之苗,不见其增日有所长;辍学如磨刀之石,不见其损日有所亏!
与君共勉!
no sacrifice ,no victory!