1. 程式人生 > 其它 >golang實現LRU演算法

golang實現LRU演算法

golang實現LRU演算法

Least Recently used

本文僅列出完成 LeetCode146.LRU快取的思路

實現:

  • 雜湊表:鍵為關鍵字key,值為*DLinkNode,對映對應連結串列中的節點
  • 雙向連結串列:靠近頭部的元素是最近使用的,靠近尾部則是最久未使用的

實現LRU並不難,建議先把演算法的各個函式的框架先列好,再去敲程式碼!!

結構:

//LRUCache定義
type LRUCache struct {
    size int     
    capacity int
    cache map[int]*DLinkNode
    head, tail *DLinkNode
}

//雙向連結串列節點
type DLinkNode struct {
    key,value int
    pre, next *DLinkNode
}

功能:

//快取實現的功能
//如果關鍵字 key 存在於快取中,則返回關鍵字的值,否則返回 -1 。
func (this *LRUCache) Get(key int) 

//如果關鍵字key 已經存在,則變更其資料值value ;如果不存在,則向快取中插入該組key-value 。如果插入操作導致關鍵字數量超過capacity ,則應該 逐出最久未使用的關鍵字
func (this *LRUCache) Put(key int, value int) 

//一些連結串列的操作
//初始化一個新節點
func initDLinkedNode(key, value int) *DLinkNode 

//更新到鏈頭,用於key命中的情況下,不改變快取的size
func (this *LRUCache) UpdateToHead(node *DLinkNode) 

//刪除鏈尾元素
func (this *LRUCache) DeleteLast()

//新增新元素,用於key未命中時,size+1
func (this *LRUCache) InsertNewHead(node *DLinkNode) 

以下附上完整程式碼

type LRUCache struct {
    size int
    capacity int
    cache map[int]*DLinkNode
    Head, Tail *DLinkNode
}

type DLinkNode struct {
    key,value int
    Pre, Next *DLinkNode
}

func InitDlinkNode(key, value int) *DLinkNode {
    return &DLinkNode{key,value,nil,nil}
}

func Constructor(capacity int) LRUCache {
    l := LRUCache{
        0,
        capacity,
        map[int]*DLinkNode{},
        InitDlinkNode(0, 0),
        InitDlinkNode(0, 0),
    }
    l.Head.Next = l.Tail
    l.Tail.Pre = l.Head
    return l
}


func (this *LRUCache) Get(key int) int {
    if _,ok := this.cache[key];!ok {
        return -1
    }
    node := this.cache[key]
    this.UpdateToHead(node)
    return node.value
}


func (this *LRUCache) Put(key int, value int)  {
    if _,ok := this.cache[key];!ok {
        node := InitDlinkNode(key, value)
        for this.size >= this.capacity {
            this.DeleteLast()
        }
        this.cache[key] = node
        this.InsertNewHead(node)
    }else {
        node := this.cache[key]
        node.value = value
        this.UpdateToHead(node)
    }
}

func (this *LRUCache) UpdateToHead(node *DLinkNode) {
    node.Pre.Next = node.Next
    node.Next.Pre = node.Pre
    temp := this.Head.Next
    this.Head.Next = node
    node.Pre = this.Head
    node.Next = temp
    temp.Pre = node
 
}

func (this *LRUCache) DeleteLast() {
    node := this.Tail.Pre
    this.Tail.Pre = node.Pre
    node.Pre.Next = node.Next
    node.Pre = nil
    node.Next = nil
    this.size--
    delete(this.cache, node.key)
}

func (this *LRUCache) InsertNewHead(node *DLinkNode) {
    temp := this.Head.Next
    this.Head.Next = node
    node.Pre = this.Head
    temp.Pre = node
    node.Next = temp
    this.size++
}