兜兜零元 发表于 2024-7-7 14:22:07

LFU算法实现

LFU (Least Frequently Used) 是一种用于缓存管理的算法。它通过跟踪每个缓存项被访问的频率来决定哪些项应该被移除。LFU算法倾向于保留那些利用频率较高的项,而移除那些利用频率较低的项。以下是LFU算法的具体先容:
工作原理


[*]计数器:每个缓存项都有一个计数器,用于记载该项被访问的次数。
[*]增加计数:每次缓存项被访问时,其计数器加一。
[*]移除策略:当缓存满时,移除计数器值最小的项。如果有多个项的计数器值类似,则根据预定规则(如最早被访问的项)移除其中一个。
实现

LFU算法的实现可以利用多种数据布局,如哈希表、双向链表和优先队列。以下是一种常见的实现方法:
利用哈希表和优先队列:

[*]哈希表 (cache):用于存储缓存项及其计数器。
[*]优先队列 (min-heap):用于快速找到计数器值最小的项。
具体步骤如下:

[*]插入/更新缓存项:

[*]如果缓存项已存在,更新其计数器并调整优先队列中的位置。
[*]如果缓存项不存在,检查缓存是否已满。如果已满,移除优先队列中计数器值最小的项,然后插入新项。

[*]访问缓存项:

[*]如果缓存项存在,更新其计数器并调整优先队列中的位置。
[*]如果缓存项不存在,返回未命中。

应用场景

LFU算法实用于以下场景:

[*]数据访问具有显着的热点数据,且热点数据相对稳固。
[*]需要高效管理缓存资源,减少缓存未命中率。
Go实现

package lfu

import (
        "container/list"
        "sync"
)

type entry struct {
        key   any
        value any
        freqint
}

type LFUCache struct {
        mtx       sync.Mutex // protects the cache
        capacityint
        size      int
        minFreq   int
        cache   map*list.Element
        frequency map*list.List
}

// NewLFUCache creates a new LFU cache
func NewLFUCache(capacity int) *LFUCache {
        return &LFUCache{
                capacity:capacity,
                cache:   make(map*list.Element),
                frequency: make(map*list.List),
        }
}

// Get retrieves a value from the cache
func (c *LFUCache) Get(key any) any {
        c.mtx.Lock()
        defer c.mtx.Unlock()
        if elem, found := c.cache; found {
                c.incrementFrequency(elem)
                return elem.Value.(*entry).value
        }
        return nil
}

// Put inserts or updates a value in the cache
func (c *LFUCache) Put(key, value any) {
        c.mtx.Lock()
        defer c.mtx.Unlock()

        if c.capacity == 0 {
                return
        }

        if elem, found := c.cache; found {
                elem.Value.(*entry).value = value
                c.incrementFrequency(elem)
        } else {
                if c.size == c.capacity {
                        c.evict()
                }
                newEntry := &entry{key, value, 1}
                if c.frequency == nil {
                        c.frequency = list.New()
                }
                elem := c.frequency.PushFront(newEntry)
                c.cache = elem
                c.minFreq = 1
                c.size++
        }
}

// incrementFrequency increases the frequency of a cache entry
func (c *LFUCache) incrementFrequency(elem *list.Element) {
        e := elem.Value.(*entry)
        oldFreq := e.freq
        e.freq++

        c.frequency.Remove(elem)
        if c.frequency.Len() == 0 {
                delete(c.frequency, oldFreq)
                if c.minFreq == oldFreq {
                        c.minFreq++
                }
        }

        if c.frequency == nil {
                c.frequency = list.New()
        }
        newElem := c.frequency.PushFront(e)
    c.cache = newElem
}

// evict removes the least frequently used cache entry
func (c *LFUCache) evict() {
        list := c.frequency
        elem := list.Back()
        if elem != nil {
                list.Remove(elem)
                delete(c.cache, elem.Value.(*entry).key)
                c.size--
        }
}https://img2023.cnblogs.com/blog/1007709/202308/1007709-20230810162948167-1526955652.jpg声明:本作品采用署名-非商业性利用-类似方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行答应,利用时请注明出处。
Author: mengbin
blog: mengbin
Github: mengbin92
cnblogs: 恋水无意
腾讯云开辟者社区:孟斯特

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: LFU算法实现