O(1)读写时间复杂度的LRU策略Cache实现

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Algorithms
{
    public class LRUImplementation
    {
        internal class CacheNode
        {
            internal CacheNode Next = null;
            internal CacheNode Previous = null;
            internal object value;
            internal string key;

            internal CacheNode(string key, object val)
            {
                this.key = key;
                this.value=val;
            }
        }
        private Dictionary<string, CacheNode> values = null;
        private int size = 0;
        private CacheNode first;
        private CacheNode last;

        public LRUImplementation(int size)
        {
            this.size = size;
            this.values = new Dictionary<string, CacheNode>(size);
            this.first = this.last = null;
        }

        public int ValueCount
        {
            get
            {
                return this.values.Count;
            }
        }

        public string[] Keys
        {
            get 
            {
                if (this.first != null)
                {
                    List<string> keyList = new List<string>();
                    CacheNode node=this.first;
                    do
                    {
                        keyList.Add(node.key);
                        node = node.Next;
                    } while (node != null);
                    return keyList.ToArray();
                }
                return null;
            }
        }

        private void RemoveLRUNode()
        {
            if (this.last != null)
            {
                this.values.Remove(this.last.key);
                this.last = this.last.Previous ;
                this.last.Next = null;
            }
        }

        public void AddValue(string key, object value)
        {
            CacheNode node = null;
            if (this.values.ContainsKey(key))
            {
                node = this.values[key];
                node.value = value;
                if (node != this.first)
                {
                    if (node.Next != null)
                    {
                        node.Next.Previous = node.Previous;
                    }
                    if (node.Previous != null)
                    {
                        node.Previous.Next = node.Next;
                    }
                }
            }
            else
            {
                node = new CacheNode(key, value);
                if (this.values.Count >= this.size)
                {
                    this.RemoveLRUNode();
                }
                this.values.Add(key, node);
            }
            if (this.first != null && this.first != node)
            {
                node.Next = this.first;
                this.first.Previous = node;
            }
            this.first = node;
            if (this.last == null)
            {
                this.last = node;
            }
        }

        public object TryGetValue(string key)
        {
            if (this.values.ContainsKey(key))
            {
                CacheNode node = this.values[key];
                if (node != this.first)
                {
                    if (node.Previous != null)
                    {
                        node.Previous.Next = node.Next;
                    }
                    if (node.Next != null)
                    {
                        node.Next.Previous = node.Previous;
                    }

                    this.first.Previous = node;
                    node.Next = this.first;
                    this.first = node;
                }
                
                return this.first.value;
            }
            return null;
        }

        public string GetBufferContent()
        {
            return string.Join(",", this.Keys);
        }
    }
}

主要使用Hashtable(Dictionary)和链表实现,能达到O(1)的读写时间复杂度。

测试代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Algorithms
{
    class Program
    {
        static void Main(string[] args)
        {
            do
            {
                int cacheSize = 0;
                bool isValid = true;
                do
                {
                    Console.WriteLine("Input cache size:");
                    isValid = int.TryParse(Console.ReadLine(), out cacheSize);
                    if (cacheSize <= 0)
                    {
                        isValid = false;
                    }
                    if (!isValid)
                    {
                        Console.WriteLine("Invalid value.");
                    }
                } 
                while (!isValid);

                LRUImplementation lru = new LRUImplementation(cacheSize);
                Random rand=new Random();

                do
                {
                    Console.WriteLine("Input key:");
                    string key = Console.ReadLine();
                    Console.WriteLine("Input value:");
                    string val = Console.ReadLine();

                    lru.AddValue(key, val);

                    Console.WriteLine("Cache content:");
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.WriteLine(lru.GetBufferContent());
                    Console.ResetColor();

                    int randIndex = rand.Next(0, lru.ValueCount - 1);
                    Console.WriteLine("Try to query the {0}th value.", randIndex);
                    lru.TryGetValue(lru.Keys[randIndex]);
                    Console.WriteLine("Cache content:");
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.WriteLine(lru.GetBufferContent());
                    Console.ResetColor();
                } while (true);
            } 
            while (true);
        }
    }
}

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。