Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 具有通用循环双链表C的LRU缓存#_C#_Generics_Doubly Linked List - Fatal编程技术网

C# 具有通用循环双链表C的LRU缓存#

C# 具有通用循环双链表C的LRU缓存#,c#,generics,doubly-linked-list,C#,Generics,Doubly Linked List,我不熟悉使用泛型,并尝试在C#中使用泛型循环双链表实现LRU缓存。我有两个问题。请帮帮我 1) 在我的LRUCache构造函数中,我正在这样做 head = new Node<T>(default(T), default(T)); head=新节点(默认值(T),默认值(T)); 这是不对的,我想用一些默认的键值对(-1,-1)数据来初始化我的头,而不是使用默认值 2) 在我的get中,我根据键检查节点是否为null,并返回默认值(T)。但是我想返回null本身 这是我

我不熟悉使用泛型,并尝试在C#中使用泛型循环双链表实现LRU缓存。我有两个问题。请帮帮我

1) 在我的LRUCache构造函数中,我正在这样做

    head = new Node<T>(default(T), default(T)); 
head=新节点(默认值(T),默认值(T));
这是不对的,我想用一些默认的键值对(-1,-1)数据来初始化我的头,而不是使用默认值

2) 在我的get中,我根据键检查节点是否为null,并返回默认值(T)。但是我想返回null本身

这是我的密码

 public class Node<T>
{
    public KeyValuePair<T, T> KeyValue { get; set; }
    public Node<T> Next { get; set; }
    public Node<T> Previous { get; set; }
    public Node(T key, T value)
    {
        this.KeyValue = new KeyValuePair<T, T>(key, value);
        Next = null;
        Previous = null;
    }
}
public class LRUCache<T>
{
    private readonly int capacity;
    private int count;
    private readonly Node<T> head;
    private readonly Dictionary<T, Node<T>> myDictionary;
    public LRUCache(int capacity)
    {
        head = new Node<T>(default(T), default(T));
        head.Next = head;
        head.Previous = head;
        this.capacity = capacity;
        myDictionary = new Dictionary<T, Node<T>>();
    }
 public void set(T key, T value)
  {
   Node<T> node;
        myDictionary.TryGetValue(key, out node);
        if (node == null)
        {
            if (this.count == this.capacity)
            {
                // remove the last element
                myDictionary.Remove(head.Previous.KeyValue.Key);
                head.Previous = head.Previous.Previous;
                head.Previous.Next = head;
                count--;
            }
            // create new node and add to dictionary
            var newNode = new Node<T>(key, value);
            myDictionary[key] = newNode;
            this.InsertAfterTheHead(newNode);
            // increase count
            count++;
        }
        else
        {
            node.KeyValue = new KeyValuePair<T, T>(key, value);
            this.MoveToFirstElementAfterHead(node);
        }
  }
 public T get(T key)
 {
        Node<T> node;
        myDictionary.TryGetValue(key, out node);
        if (node == null)
        {
            return default(T);

        }
        this.MoveItToFirstElementAfterHead(node);
        return node.KeyValue.Value;
 }
}
公共类节点
{
public KeyValuePair KeyValue{get;set;}
公共节点下一个{get;set;}
公共节点前一个{get;set;}
公共节点(T键,T值)
{
this.KeyValue=新的KeyValuePair(键,值);
Next=null;
Previous=null;
}
}
公共类LRUCache
{
专用只读int容量;
私人整数计数;
专用只读节点头;
私人只读词典;
公共LRUCache(内部容量)
{
头=新节点(默认值(T),默认值(T));
head.Next=head;
head.Previous=head;
这个。容量=容量;
myDictionary=新字典();
}
公共无效集(T键,T值)
{
节点;
TryGetValue(键,out节点);
if(node==null)
{
if(this.count==this.capacity)
{
//删除最后一个元素
myDictionary.Remove(head.Previous.KeyValue.Key);
head.Previous=head.Previous.Previous;
head.Previous.Next=头;
计数--;
}
//创建新节点并添加到字典
var newNode=新节点(键、值);
myDictionary[key]=newNode;
这个。在头部后面插入(新节点);
//增加计数
计数++;
}
其他的
{
node.KeyValue=新的KeyValuePair(键,值);
此.MoveToFirstElementAfterHead(节点);
}
}
公共T获取(T键)
{
节点;
TryGetValue(键,out节点);
if(node==null)
{
返回默认值(T);
}
this.MoveItToFirstElementAfterHead(节点);
返回node.KeyValue.Value;
}
}

假设节点中包含的值是包含用作键的属性的类,请尝试以下操作:

public abstract class Node<TNode, TNodeSupport, TKey, TValue>
    where TNode : Node<TNode, TNodeSupport, TKey, TValue>
    where TNodeSupport : Node<TNode, TNodeSupport, TKey, TValue>.BaseNodeSupport, new()
    where TValue : class
{
    protected static readonly TNodeSupport Support = new TNodeSupport();

    public KeyValuePair<TKey, TValue> KeyValue { get; set; }
    public TNode Next { get; set; }
    public TNode Previous { get; set; }
    protected Node(TValue value)
    {
        this.KeyValue = new KeyValuePair<TKey, TValue>(Support.GetKeyFromValue(value), value);
        Next = null;
        Previous = null;
    }

    public class LRUCache
    {
        private readonly int capacity;
        private int count;
        private readonly TNode head;
        private readonly Dictionary<TKey, TNode> myDictionary;
        public LRUCache(int capacity)
        {
            head = Support.CreateHeadNode();
            head.Next = head;
            head.Previous = head;
            this.capacity = capacity;
            myDictionary = new Dictionary<TKey, TNode>();
        }
        public void set(TValue value)
        {
           TKey key = Support.GetKeyFromValue(value);
           TNode node;
           myDictionary.TryGetValue(key, out node);
           if (node == null)
           {
              if (this.count == this.capacity)
              {
                    // remove the last element
                   myDictionary.Remove(head.Previous.KeyValue.Key);
                   head.Previous = head.Previous.Previous;
                   head.Previous.Next = head;
                   count--;
               }
               // create new node and add to dictionary
               var newNode = Support.CreateNodeFromValue(value);
               myDictionary[key] = newNode;
               this.InsertAfterTheHead(newNode);
               // increase count
               count++;
           }
           else
           {
               node.KeyValue = new KeyValuePair<TKey, TValue>(key, value);
                this.MoveToFirstElementAfterHead(node);
           }
        }
        public TValue get(TKey key)
        {
            TNode node;
            myDictionary.TryGetValue(key, out node);
            if (node == null)
            {
                return null;

            }
            this.MoveItToFirstElementAfterHead(node);
            return node.KeyValue.Value;
        }
    }

    public abstract class BaseNodeSupport
    {
        public abstract TKey GetKeyFromValue(TValue value);
        public abstract TNode CreateNodeFromValue(TValue value);
        public abstract TNode CreateHeadNode();
    }

}
在这个解决方案中,Node是一个类和一个通用/参数化名称空间,用于保存来自第三方库或本地定义的项

TNodeSupport类作为一个单例使用,它提供了在整个节点命名空间中使用的三个支持函数。第一个函数接受一个项并从该项返回键。第二个函数从一个项创建一个TNode。第三个函数使用默认的空项创建默认的头部节点

LRUCache包含在节点泛型名称空间中,因此它可以访问其运行所需的泛型类型参数。LRUCache逻辑实现与作者的原始实现基本相同

在定义子类节点的示例中,ItemNode是一个参数化的子类/子名称空间。ItemNode为TNode参数指定自身,为TNodeSupport参数指定ItemNode.NodeSupport,为TKey参数指定Guid,为TValue参数指定Item

Item类是一个精心设计的类,包含一些数据和一个Id,该Id将用作项的键

Item.NodeSupport类派生自Node.BaseNodeSupport类并重写三个支持函数。在GetKeyFromValue方法中,它返回提供的项实例的Id属性。在CreateNodeFromValue方法中,它返回使用提供的Item实例构造的ItemNode。在CreateHeadNode方法中,它返回一个新的ItemNode,该ItemNode由一个新项构造,该项包含一个Guid.Empty作为Id,一个String.Empty作为数据


在Program类中,我们实例化ItemNode.LRUCache以包含包含项的ItemNode实例。

假设节点中包含的值是包含用作键的属性的类,请尝试以下操作:

public abstract class Node<TNode, TNodeSupport, TKey, TValue>
    where TNode : Node<TNode, TNodeSupport, TKey, TValue>
    where TNodeSupport : Node<TNode, TNodeSupport, TKey, TValue>.BaseNodeSupport, new()
    where TValue : class
{
    protected static readonly TNodeSupport Support = new TNodeSupport();

    public KeyValuePair<TKey, TValue> KeyValue { get; set; }
    public TNode Next { get; set; }
    public TNode Previous { get; set; }
    protected Node(TValue value)
    {
        this.KeyValue = new KeyValuePair<TKey, TValue>(Support.GetKeyFromValue(value), value);
        Next = null;
        Previous = null;
    }

    public class LRUCache
    {
        private readonly int capacity;
        private int count;
        private readonly TNode head;
        private readonly Dictionary<TKey, TNode> myDictionary;
        public LRUCache(int capacity)
        {
            head = Support.CreateHeadNode();
            head.Next = head;
            head.Previous = head;
            this.capacity = capacity;
            myDictionary = new Dictionary<TKey, TNode>();
        }
        public void set(TValue value)
        {
           TKey key = Support.GetKeyFromValue(value);
           TNode node;
           myDictionary.TryGetValue(key, out node);
           if (node == null)
           {
              if (this.count == this.capacity)
              {
                    // remove the last element
                   myDictionary.Remove(head.Previous.KeyValue.Key);
                   head.Previous = head.Previous.Previous;
                   head.Previous.Next = head;
                   count--;
               }
               // create new node and add to dictionary
               var newNode = Support.CreateNodeFromValue(value);
               myDictionary[key] = newNode;
               this.InsertAfterTheHead(newNode);
               // increase count
               count++;
           }
           else
           {
               node.KeyValue = new KeyValuePair<TKey, TValue>(key, value);
                this.MoveToFirstElementAfterHead(node);
           }
        }
        public TValue get(TKey key)
        {
            TNode node;
            myDictionary.TryGetValue(key, out node);
            if (node == null)
            {
                return null;

            }
            this.MoveItToFirstElementAfterHead(node);
            return node.KeyValue.Value;
        }
    }

    public abstract class BaseNodeSupport
    {
        public abstract TKey GetKeyFromValue(TValue value);
        public abstract TNode CreateNodeFromValue(TValue value);
        public abstract TNode CreateHeadNode();
    }

}
在这个解决方案中,Node是一个类和一个通用/参数化名称空间,用于保存来自第三方库或本地定义的项

TNodeSupport类作为一个单例使用,它提供了在整个节点命名空间中使用的三个支持函数。第一个函数接受一个项并从该项返回键。第二个函数从一个项创建一个TNode。第三个函数使用默认的空项创建默认的头部节点

LRUCache包含在节点泛型名称空间中,因此它可以访问其运行所需的泛型类型参数。LRUCache逻辑实现与作者的原始实现基本相同

在定义子类节点的示例中,ItemNode是一个参数化的子类/子名称空间。ItemNode为TNode参数指定自身,为TNodeSupport参数指定ItemNode.NodeSupport,为TKey参数指定Guid,为TValue参数指定Item

Item类是一个精心设计的类,包含一些数据和一个Id,该Id将用作项的键

Item.NodeSupport类派生自Node.BaseNodeSupport类并重写三个支持函数。在GetKeyFromValue方法中,它返回提供的项实例的Id属性。在CreateNodeFromValue方法中,它返回使用提供的Item实例构造的ItemNode。在CreateHeadNode方法中,它返回一个新的ItemNode,该ItemNode由一个新项构造,该项包含一个Guid.Empty作为Id,一个String.Empty作为数据

在程序类中,我们使用instantia
public class Program
{
    static void Main()
    {
        var cache = new ItemNode.LRUCache(100);
    }
}