C#簡單實現LRU緩存


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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM