最近跟同学吃饭扯淡的时候,由技术扯到薪资,又由薪资扯到他找工作时跟面试官是怎么扯淡拿高工资的,各种技术一顿侃,总之只要啥都了解就没问题了。谈到缓存的时候,我试探性的问了问- -你还记得LRU怎么写吗,他说啥完?我说没事。。
写完这篇文章发给他- -鄙视完他让他请我再吃饭,标准的缓存LRU实现为哈希表+链表,这是热乎的双向链表,也是C#版本的。。C#实现双向链表
代码:
public class LRUCache<T> { private int _size;//链表长度 private int _capacity;//缓存容量 private Dictionary<int, ListNode<T>> _dic;//key +缓存数据 private ListNode<T> _linkHead; public LRUCache(int capacity) { _linkHead = new ListNode<T>(-1, default(T)); _linkHead.Next = _linkHead.Prev = _linkHead; this._size = 0; this._capacity = capacity; this._dic = new Dictionary<int, ListNode<T>>(); } public T Get(int key) { if (_dic.ContainsKey(key)) { ListNode<T> n = _dic[key]; MoveToHead(n); return n.Value; } else { return default(T); } } public void Set(int key, T value) { ListNode<T> n; if (_dic.ContainsKey(key)) { n = _dic[key]; n.Value = value; MoveToHead(n); } else { n = new ListNode<T>(key, value); AttachToHead(n); _size++; } if (_size > _capacity) { RemoveLast();// 如果更新节点后超出容量,删除最后一个 _size--; } _dic.Add(key, n); } // 移出链表最后一个节点 private void RemoveLast() { ListNode<T> deNode = _linkHead.Prev; RemoveFromList(deNode); _dic.Remove(deNode.Key); } // 将一个孤立节点放到头部 private void AttachToHead(ListNode<T> n) { n.Prev = _linkHead; n.Next = _linkHead.Next; _linkHead.Next.Prev = n; _linkHead.Next = n; } // 将一个链表中的节点放到头部 private void MoveToHead(ListNode<T> n) { RemoveFromList(n); AttachToHead(n); } private void RemoveFromList(ListNode<T> n) { //将该节点从链表删除 n.Prev.Next = n.Next; n.Next.Prev = n.Prev; } } public class ListNode<T> { public ListNode<T> Prev; public ListNode<T> Next; public T Value; public int Key; public ListNode(int key, T val) { Value = val; Key = key; this.Prev = null; this.Next = null; } }
测试:
LRUCache<int> cache = new LRUCache<int>(3); cache.Get(1); cache.Set(1, 1); cache.Set(2, 2); cache.Get(3); cache.Set(3, 3); cache.Set(4, 4); cache.Get(2);