最近跟同學吃飯扯淡的時候,由技術扯到薪資,又由薪資扯到他找工作時跟面試官是怎么扯淡拿高工資的,各種技術一頓侃,總之只要啥都了解就沒問題了。談到緩存的時候,我試探性的問了問- -你還記得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);