LRU算法實現(xiàn)

package main

import (
    "fmt"
)

// 定義節(jié)點(diǎn)結(jié)構(gòu)體
type node struct {
    key   string
    value string
    next  *node
    prev  *node
}

// 定義lru結(jié)構(gòu)體
type lru struct {
    //緩存最大數(shù)量
    k int
    // 存放節(jié)點(diǎn)數(shù)據(jù)
    cache map[string]*node
    //頭節(jié)點(diǎn)
    head *node
    // 尾節(jié)點(diǎn)
    tail *node
}

// 工廠方法,構(gòu)造一個LRU緩存對象
func NewLRUCache(k int) *lru {
    return &lru{k: k}
}

// 對外開放的Get方法
func (lru *lru) Get(key string) string {
    if lru.cache == nil {
        return ""
    }
    n, ok := lru.cache[key]
    if ok {
        value := n.value
        //更新到頭節(jié)點(diǎn)
        lru.moveNodeToHead(n)
        return value
    } else {
        return ""
    }
}

// 對外開放的Set方法
func (lru *lru) Set(key string, value string) {
    //初始化map
    if lru.cache == nil {
        lru.cache = make(map[string]*node)
    }
    n, ok := lru.cache[key]
    if ok {
        //更新緩存
        n.value = value
    } else {
        //創(chuàng)建新節(jié)點(diǎn)
        n = &node{key: key, value: value}
        // 添加到map中
        lru.cache[key] = n
        //如果超過緩存大小,移除最后一個節(jié)點(diǎn)
        if len(lru.cache) > lru.k {
            lru.removeTail()
        }
    }
    // 更新節(jié)點(diǎn)為頭節(jié)點(diǎn)
    lru.moveNodeToHead(n)
}

//將指定節(jié)點(diǎn)移到頭節(jié)點(diǎn)
func (lru *lru) moveNodeToHead(n *node) {
    //如果頭節(jié)點(diǎn)和尾節(jié)點(diǎn)都是空,說明是第一次添加數(shù)據(jù)
    if lru.head == nil && lru.tail == nil {
        lru.head = n
        lru.tail = n
        return
    }
    // 如果是頭節(jié)點(diǎn),那么不動
    if lru.head == n {
        return
    }
    nextNode := n.next
    prevNode := n.prev
    // 如果是尾節(jié)點(diǎn),那么要先與上一個節(jié)點(diǎn)斷開
    if n == lru.tail {
        prevNode.next = nil
        n.prev = nil
    } else if prevNode != nil && nextNode != nil {
        //如果是中間節(jié)點(diǎn),要與前后節(jié)點(diǎn)都斷開
        nextNode.prev = prevNode
        prevNode.next = nextNode
        n.prev = nil
    }
    //把節(jié)點(diǎn)移到到頭節(jié)點(diǎn)
    n.next = lru.head
    lru.head.prev = n
    lru.head = n
}

//移除最后一個節(jié)點(diǎn)
func (lru *lru) removeTail() {
    // 如果尾節(jié)點(diǎn)wei空,那么清空數(shù)據(jù)直接返回
    if lru.tail == nil {
        lru.cache = nil
        return
    }
    tailPrev := lru.tail.prev
    // 尾節(jié)點(diǎn)與上一個節(jié)點(diǎn)斷開
    lru.tail.prev = nil
    if tailPrev != nil {
        tailPrev.next = nil
    }
    // 把上一個節(jié)點(diǎn)置為尾節(jié)點(diǎn)
    lru.tail = tailPrev
    // 從map中刪除尾節(jié)點(diǎn)數(shù)據(jù)
    delete(lru.cache, lru.tail.key)
}

// 重寫String方法,自定義打印結(jié)果
func (lru *lru) String() string {
    point := lru.head
    result := ""
    flag := "\t"
    for point != nil {
        if len(result) > 0 {
            result = fmt.Sprintf("%v%v[%v:%v]", result, flag, point.key, point.value)
        } else {
            result = fmt.Sprintf("[%v:%v]", point.key, point.value)
        }
        point = point.next
    }
    return result
}

func main() {
    LRUCache := NewLRUCache(5)
    LRUCache.Set("1", "1")
    LRUCache.Set("2", "2")
    LRUCache.Set("3", "3")
    LRUCache.Set("4", "4")
    LRUCache.Set("5", "5")
    //打印緩存數(shù)據(jù),驗證容量是否起作用
    fmt.Println(LRUCache)
    //設(shè)置超過最大容量的數(shù)據(jù)
    LRUCache.Set("6", "6")
    //打印緩存數(shù)據(jù),驗證超過容量是否起作用
    fmt.Println(LRUCache)
    //查詢頭節(jié)點(diǎn)數(shù)據(jù)
    fmt.Println(LRUCache.Get("6"))
    //打印緩存數(shù)據(jù)
    fmt.Println(LRUCache)
    //查詢非頭節(jié)點(diǎn)數(shù)據(jù)
    fmt.Println(LRUCache.Get("4"))
    //打印緩存數(shù)據(jù)
    fmt.Println(LRUCache)
    //查詢尾節(jié)點(diǎn)數(shù)據(jù)
    fmt.Println(LRUCache.Get("2"))
    //打印緩存數(shù)據(jù)
    fmt.Println(LRUCache)
}
image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容