• LRU的map+双链表实现(Go描述)


    面云账户时候问了LRU,具体实现的方式是map+双链表。Set和Get的时间复杂度都是O(1)。完整写一遍复习一下, 仅作记录

    /**
     * @Author: lzw5399
     * @Date: 2021/5/20 22:28
     * @Desc: 基于map和双链表实现的LRU算法
     */
    package main
    
    import "sync"
    
    func main() {
    	lru := NewLRUCache(3)
    
    	lru.Set(1, 233)
    	lru.Set(2, 666)
    	lru.Set(3, 777)
    	lru.Set(5, 888)
    
    	lru.Get(2)
    }
    
    // LRUCache
    type LRUCache struct {
    	capacity int
    	cache    map[int]*LinkedNode
    	head     *LinkedNode
    	tail     *LinkedNode
    	sync.RWMutex
    }
    
    type LinkedNode struct {
    	key, value int
    	prev, next *LinkedNode
    }
    
    func NewLRUCache(capacity int) *LRUCache {
    	return &LRUCache{
    		capacity: capacity,
    		cache:    make(map[int]*LinkedNode, capacity),
    		head:     nil,
    		tail:     nil,
    		RWMutex:  sync.RWMutex{},
    	}
    }
    
    // - key是否已存在
    //   - 已存在, 将该节点移动到链表头部
    //   - 未存在, 判断cap是否已满
    //     - 满
    //       - 移除链表尾的节点
    //       - 新的node放入链表头
    //       - 新的node放入cache的map中
    //     - 未满
    //       - 新的node放入链表头
    //       - 新的node放入cache的map中
    func (l *LRUCache) Set(key int, value int) {
    	l.RLock()
    	node, exist := l.cache[key]
    	l.RUnlock()
    	if exist {
    		l.moveToHead(node)
    		return
    	}
    
    	node = &LinkedNode{
    		key:   key,
    		value: value,
    	}
    
    	l.Lock()
    	defer l.Unlock()
    
    	if l.capacity == len(l.cache) {
    		removedNode := l.removeTail()
    		delete(l.cache, removedNode.key)
    	}
    
    	l.addToHead(node)
    	l.cache[key] = node
    }
    
    // - 从map中获取是否存在
    //   - 不存在
    //     - 返回-1
    //   - 存在
    //     - 移到链表头部
    //     - 并返回具体的值
    func (l *LRUCache) Get(key int) int {
    	l.RLock()
    	node, exist := l.cache[key]
    	l.RUnlock()
    	if !exist {
    		return -1
    	}
    
    	l.moveToHead(node)
    	return node.value
    }
    
    func (l *LRUCache) moveToHead(node *LinkedNode) {
    	l.removeNode(node)
    	l.addToHead(node)
    }
    
    func (l *LRUCache) removeTail() *LinkedNode {
    	return l.removeNode(l.tail)
    }
    
    func (l *LRUCache) removeNode(node *LinkedNode) *LinkedNode {
    	// 头节点
    	if node.prev == nil {
    		l.head = node.next
    		node.next.prev = nil
    		return node
    	}
    
    	// 尾节点
    	if node.next == nil {
    		l.tail = node.prev
    		node.prev.next = nil
    		return node
    	}
    
    	// 中间节点
    	node.prev.next = node.next
    	node.next.prev = node.prev
    	return node
    }
    
    func (l *LRUCache) addToHead(node *LinkedNode) {
    	if l.head == nil {
    		l.tail = node
    	} else {
    		l.head.prev = node
    	}
    
    	node.prev = nil
    	node.next = l.head
    	l.head = node
    }
    
    
  • 相关阅读:
    【HDOJ】1243 反恐训练营
    Eclipse 点击 Run 自动生成 out 文件的错误
    经纬度转凯立德 K 码
    Android开发环境建立
    Android 学习过程中遇到的知识点
    Android
    Android
    素数距离问题
    取石子(一)
    素数求和问题
  • 原文地址:https://www.cnblogs.com/baoshu/p/14794330.html
Copyright © 2020-2023  润新知