C#数据结构支持以下内容

本文关键字:数据结构 支持 | 更新日期: 2023-09-27 18:27:20

我需要一个以以下方式工作的C#数据结构:

  1. 用静态大小定义
  2. 将新数据添加到列表末尾
  3. 最旧的数据会减少
  4. 数据元素的随机访问

示例:如果我定义了一个由5个元素组成的结构,并添加了以下

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

数据结构如下所示:

4,5,6,7,8

我不确定哪种结构会以这种方式工作。矢量?列表堆栈数据结构支持像数组这样的静态大小,并支持推送旧数据的数据。

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

也许是LinkedList并为"push"添加自定义操作,以删除第一个元素?不过,链表随机访问是o(n)操作。

C#数据结构支持以下内容

为了最大限度地提高效率,这可能是一个实现循环缓冲区的自定义类。

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

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

添加项目时,它将进入元素(start + size) % capacity,如果size还不在capacity,则它将递增。如果capacity时为,则也可以递增start,如果需要,则环绕为:start = (start + 1) % capacity

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

return element[(start + n) % capacity];

我还没有谈到删除列表的开头,因为这不在你的规格中。然而,这是一个简单的检查,以确保size不是0,然后在element[start]提取项目,然后用上面显示的相同环绕来递增start

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

def listNew (capacity):
    me = new object
    me.capacity = capacity
    me.data = new array[capacity]
    me.start = 0
    me.size = 0
    return me
def listAdd (me, item):
    if me.size = me.capacity:
        me.data[me.start] = item
        me.start = (me.start + 1) % me.capacity
    else:
        me.data[(me.start + me.size) % me.capacity] = item
        me.size = me.size + 1
def listGet (me, index):
    if index > size:
        return 0 # or raise error of some sort
    return me.data[(me.start + index) % me.capacity]
def listRemove (me):
    if size == 0:
        return 0 # or raise error of some sort
    item = me.data[(me.start + index) % me.capacity]
    me.start = (me.start + 1) % me.capacity
    me.size = me.size - 1
    return item

根据要求,所有这些操作都具有O(1)时间复杂性。

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

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

这样,从缓冲区中提取虚拟索引3(第四个数字)会得到一个实际索引:

  (start + 3) % capacity
= (  3   + 3) %    5
=       6     %    5
=             1

这是一个最大长度的队列(因此,一旦达到最大长度,您必须先取消队列并丢弃一个元素,然后再对另一个元素进行排队)。你可以对C#队列进行随机访问,但它是O(n)(使用ElementAt LINQ扩展),如果5是一个典型的大小,这可能不是一个真正的问题。如果你想要O(1),我怀疑你必须自己滚(https://github.com/mono/mono/blob/master/mcs/class/System/System.Collections.Generic/Queue.cs?source=cc可能会有所帮助!)

Queue在这种情况下是最好的,您应该编写自己的包装类,在Enqueue(将新数据添加到列表末尾)之前检查您的计数(限制),使其表现得像一个固定的计数,这里有一个示例:

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));
    }
}