// LFU the Least Frequently Used (LFU) page-replacement algorithm type LFU struct { lenint// length capint// capacity minFreq int// The element that operates least frequently in LFU
// key: key of element, value: value of element itemMap map[string]*list.Element
// key: frequency of possible occurrences of all elements in the itemMap // value: elements with the same frequency freqMap map[int]*list.List // 维护一个频率和list的集合 }
我们使用LFU算法的话,我们插入的元素就需要带上频率了
funcinitItem(k string, v any, f int)item { return item{ key: k, value: v, freq: f, } }
如果我们获取某个元素,那么这个元素如果存在,就会对这个元素的频率进行加1
func(c *LFU)Get(key string)any { // if existed, will return value if e, ok := c.itemMap[key]; ok { // the frequency of e +1 and change freqMap c.increaseFreq(e) obj := e.Value.(item) return obj.value }
// if not existed, return nil returnnil }
增加频率
func(c *LFU)increaseFreq(e *list.Element) { obj := e.Value.(item) // remove from low frequency first oldLost := c.freqMap[obj.freq] oldLost.Remove(e) // change the value of minFreq if c.minFreq == obj.freq && oldLost.Len() == 0 { // if it is the last node of the minimum frequency that is removed c.minFreq++ } // add to high frequency list c.insertMap(obj) }
插入key到LFU缓存中
如果存在就对频率加1
如果不存在就准备插入
如果溢出了,就把最少频率的删除
如果没有溢出,那么就放到最后
// Put the key in LFU cache func(c *LFU)Put(key string, value any) { if e, ok := c.itemMap[key]; ok { // if key existed, update the value obj := e.Value.(item) obj.value = value c.increaseFreq(e) } else { // if key not existed obj := initItem(key, value, 1) // if the length of item gets to the top line // remove the least frequently operated element if c.len == c.cap { c.eliminate() c.len-- } // insert in freqMap and itemMap c.insertMap(obj) // change minFreq to 1 because insert the newest one c.minFreq = 1 // length++ c.len++ } }
插入一个新的
func(c *LFU)insertMap(obj item) { // add in freqMap l, ok := c.freqMap[obj.freq] if !ok { l = list.New() c.freqMap[obj.freq] = l } e := l.PushFront(obj) // update or add the value of itemMap key to e c.itemMap[obj.key] = e }
找到频率最少的链表,并且删除
func(c *LFU)eliminate() { l := c.freqMap[c.minFreq] e := l.Back() obj := e.Value.(item) l.Remove(e)