什么C#数据结构支持以下?

时间:2013-08-12 02:32:59

标签: c# data-structures

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

  1. 使用静态大小定义
  2. 将新数据添加到列表末尾
  3. 最旧的数据下降。
  4. 随机访问数据元素
  5. 示例:如果我定义了5个元素的结构并添加了以下内容

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

    数据结构如下所示:

    4,5,6,7,8

    我不确定哪种结构会以这种方式运作。向量?名单?堆?数据结构支持像数组一样的静态大小,并推送推送旧数据的数据。

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

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

3 个答案:

答案 0 :(得分:5)

为了获得最大效率,这可能是实现循环缓冲区的自定义类。

只需在实例化时创建一个固定大小的数组来保存数据。另外还有一个起始索引,一个大小成员和一个容量,这样你就可以知道缓冲区中的数据量和起始位置。

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

当您添加项目时,它会进入元素(start + size) % capacity,如果size尚未在capacity,则capacity会增加。如果 位于start,则您也会增加start = (start + 1) % capacity,如果需要,请将其包围:n

要从列表中获取索引start的元素,您实际上是使用return element[(start + n) % capacity]; 进行调整:

size

我没有介绍删除列表的开头,因为那不在您的规范中。但是,这是一个简单的检查,以确保element[start]不为0,然后在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

在伪代码中(未经测试但应该关闭):

1

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

对于将数字8 0 1 2 3 4 <--- index +---+---+---+---+---+ | 6 | 7 | 8 | 4 | 5 | +---+---+---+---+---+ ^ +--------- start = 3 size = 5 capacity = 5 添加到五元素列表的特定示例,您最终会得到:

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

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

{{1}}

答案 1 :(得分:2)

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

答案 2 :(得分:0)

在这种情况下队列是最好的,你应该编写自己的包装类,在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));
    }
}