什么样的C#数据结构支持以下内容?

什么样的C#数据结构支持以下内容?,c#,data-structures,C#,Data Structures,我需要一个C#数据结构,其工作方式如下: 使用静态大小定义它 将新数据添加到列表末尾 最旧的数据会丢失 数据元素的随机存取 示例:如果我定义了一个由5个元素组成的结构,并添加了以下内容 1,2,3,4,5,6,7,8 数据结构如下所示: 4,5,6,7,8 我不确定哪种结构会以这种方式工作。矢量?列表堆栈数据结构支持静态大小(如数组)和推送数据(推送旧数据) 堆栈/队列不提供随机访问。 列表没有“推送”操作 也许是一个LinkedList并为删除第一个元素的“push”添加自定义操作?链接列表随

我需要一个C#数据结构,其工作方式如下:

  • 使用静态大小定义它
  • 将新数据添加到列表末尾
  • 最旧的数据会丢失
  • 数据元素的随机存取
  • 示例:如果我定义了一个由5个元素组成的结构,并添加了以下内容

    1,2,3,4,5,6,7,8

    数据结构如下所示:

    4,5,6,7,8

    我不确定哪种结构会以这种方式工作。矢量?列表堆栈数据结构支持静态大小(如数组)和推送数据(推送旧数据)

    堆栈/队列不提供随机访问。 列表没有“推送”操作


    也许是一个LinkedList并为删除第一个元素的“push”添加自定义操作?链接列表随机访问是o(n)操作。

    它是一个最大长度的队列(因此,当一个元素达到最大长度时,您必须先取消队列并丢弃它,然后再对另一个元素进行排队)。您可以在C#队列上进行随机访问,但它是O(n)(使用ElementAt LINQ扩展),如果5是一个典型的大小,这可能不是一个真正的问题。如果您想要O(1),我想您必须自己滚动(可能会有帮助!)

    以获得最大效率,这可能是一个实现循环缓冲区的自定义类

    只需在实例化时创建一个固定大小的数组来保存数据。此外,还需要一个开始索引、一个大小成员和一个容量,这样您就可以知道缓冲区中有多少数据以及数据从哪里开始

    因此,首先,列表不包含任何数据,开始位置为0,大小为0

    当您添加一个项目时,它进入元素
    (开始+大小)%capacity
    ,并且
    大小
    如果尚未达到
    容量
    ,则会增加。如果是
    容量
    ,您还可以增加
    开始
    ,如果需要,可以将其环绕:
    开始=(开始+1)%capacity

    要从列表中获取索引
    n
    处的元素,实际上可以使用
    start
    对其进行调整:

    return element[(start + n) % capacity];
    
    我没有提到删除列表的开头,因为这不在您的规范中。但是,这是一个简单的检查,以确保
    大小
    不是0,然后在
    元素[start]
    处提取项目,然后以上面所示的相同换行方式递增
    开始

    在伪代码中(未测试,但应接近):

    根据要求,所有这些操作的时间复杂度都是O(1)

    对于将数字
    1
    通过
    8
    添加到五元素列表的特定示例,您将得到:

      0   1   2   3   4 <--- index
    +---+---+---+---+---+
    | 6 | 7 | 8 | 4 | 5 |
    +---+---+---+---+---+
                  ^
                  +--------- start    = 3
                             size     = 5
                             capacity = 5
    

    在这种情况下,队列是最好的,您应该编写自己的包装器类,在排队(向列表末尾添加新数据)之前检查您的计数(限制),使其像固定数据一样工作,下面是一个示例:

    public class FixedQueue<T> : Queue<T>
    {
    //to sets the total number of elements that can be carried without resizing,
    //we called the base constrctor that takes the capacity
        private Random random;
        public int Size { get; private set; }
    
        public FixedQueue(int size, Random random)
            :base(size)                 
        {
             this.Size = size;
             this.random = random;
        }
    
        public new void Enqueue(T element)
        {
            base.Enqueue(element);
            lock (this)
                while (base.Count > Size)
                    base.Dequeue();  //as you said, "Oldest data falls off" :)
        }
    
        public T RandomAcess()
        {
            return this.ElementAt(random.Next(Count));
        }
    }
    
    公共类固定队列:队列
    {
    //要设置无需调整大小即可携带的元素总数,
    //我们打电话给承担容量的基础构造师
    私有随机;
    公共整数大小{get;私有集;}
    公共固定队列(整数大小,随机)
    :底座(尺寸)
    {
    这个。大小=大小;
    这个。随机=随机;
    }
    公共新空队列(T元素)
    {
    基本队列(元素);
    锁(这个)
    while(base.Count>大小)
    base.Dequeue();//正如您所说,“最早的数据会丢失”:
    }
    公共T随机性()
    {
    返回此.ElementAt(random.Next(Count));
    }
    }
    
    因此,请根据您的需求创建自己的数据结构。谢谢。还有可能有用的fixed语句。@Curtiswite该
    fixed
    语句只适用于不安全的上下文,而在这里肯定不适用。这是C#知识的“高级”领域,只有当您使用本机(非.Net)代码进行Interop/PInvoke时才真正有用。@Pax乍一看,这似乎是一个非常好的实现@Curtis,是的,乍一看还不错。不存在非满缓冲区的概念(它总是被认为是满的),但是如果你需要的话,可以很容易地添加。我不认为这就是OP所说的“随机访问”,尽管我必须承认它引起了一个微笑:-)随机访问OP要求的是在不遍历其他元素的情况下访问任何元素的能力,不是随机访问元素的能力。在任何情况下,我认为队列中的ElementAt是O(n)而不是O(1)。
      (start + 3) % capacity
    = (  3   + 3) %    5
    =       6     %    5
    =             1
    
    public class FixedQueue<T> : Queue<T>
    {
    //to sets the total number of elements that can be carried without resizing,
    //we called the base constrctor that takes the capacity
        private Random random;
        public int Size { get; private set; }
    
        public FixedQueue(int size, Random random)
            :base(size)                 
        {
             this.Size = size;
             this.random = random;
        }
    
        public new void Enqueue(T element)
        {
            base.Enqueue(element);
            lock (this)
                while (base.Count > Size)
                    base.Dequeue();  //as you said, "Oldest data falls off" :)
        }
    
        public T RandomAcess()
        {
            return this.ElementAt(random.Next(Count));
        }
    }