如何移动元素?

时间:2015-06-07 02:54:33

标签: c# .net queue

假设您在.NET中有一个Queue实例(Systems.Generic.Collections.Queue)。该队列有10个元素,其中元素9(从0开始计数)是队列中最近添加的元素。

所以队列看起来像这样:

{0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0}

其中0.1是Dequeue上要弹出的下一个元素,1.0是最近添加的项目。

我想删除最近添加的5个项目 队列最终看起来像这样(我需要在队列中保持相同数量的元素,因此大小不会减少):

{0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5}

在.NET中实现这一目标的最快方法是什么

澄清:

t = 0:队列已初始化

{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}

t = 1:添加一个元素

{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1}

t = 2:添加了一个元素

{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.2}

t = 3:添加了一个元素

{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.2, 0.3}

t = 4:最近添加的两个元素是"删除" (及时倒退)

{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1}

背景资料:

我将样品推到缓冲液中。缓冲区基本上是长流样本上的滑动窗口。有时我想"倒带"窗户;那就是:及时移回它,因为我推的样品应该被丢弃。我不知道是否应该提前丢弃样品。我必须推动样品,对"窗口中的样品进行一些计算。然后决定窗口是否应该"备份"及时。

更新

要求:

  1. 实现具有N个固定大小的缓冲区X.缓冲区中最旧的元素位于索引0(X [0])。缓冲区中的最新元素是索引N-1(X [N-1])

  2. 实施方法'写'它将一个样本s写入缓冲区。当样本写入缓冲区时,缓冲区中的样本将被移位 对于j = 0到j = N-2且X [N-1] = s,X [j] = X [j + 1]。

  3. 在任何给定时间,都应提供以下方法:

    • 在缓冲区中查找最大样本值
    • 在缓冲区中查找最小样本值
    • 查找缓冲区中样本值的平均值
    • 在缓冲区中的任意位置读取样本值
  4. "倒带":实现一个方法,复制从索引0到索引K-1的K个元素,并将它们放在缓冲区的末尾。因此,最初在索引K-1处的样本将移动到索引N-1,并且最初在索引0处的样本移动到索引(N-1) - (K-1)。索引0到索引K-1的样本随后设置为0.

  5. 我希望上面说明我想要的东西。感谢。

3 个答案:

答案 0 :(得分:1)

所以,根据你的新要求,我会实现这个类:

public class Buffer
{
    public Buffer(int N) { }
    public void Write(double value) { }
    public double Maximum { get { return 0.0; } }
    public double Minimum { get { return 0.0; } }
    public double Average { get { return 0.0; } }
    public double this[int n] { get { return 0.0; } }
    public void Rewind(int k) { }
}

这段代码显然只是shell - 我已经将内部工作留给你进行编码了。

我精确地遵循了你的要求结构。

目前编写的代码应该有助于使其成为一个很好的起点。

我建议您首先使用数组作为基础数据结构(即double[N])来实现。如果您实现此代码并且它足够有效,那么您就完成了。如果没有,那么尝试使用LinkedList<double> - 这将更难编码,但它应该更快,虽然没有运行你的代码,我无法告诉你。

答案 1 :(得分:1)

虽然您对Rewind操作的预期行为仍然有些不清楚,但您似乎需要类似固定大小ring buffer的内容。因此,如果我误解了应该如何工作,请在您的问题中进一步澄清。

public class RewindableRingBuffer<T>
{
    private readonly T[] _values;
    private int _head;  // index of oldest value
    private int _count; // number of elements

    public RewindableRingBuffer(int capacity)
    {
        _values = new T[capacity];
        _head = 0;
        _count = 0;
    }

    public int Count { get { return _count; } }

    public T this[int index]
    {
        get 
        {
            if ((uint)index >= (uint)_count)
                throw new IndexOutOfRangeException("index");
            return _values[(_head + index) % _values.Length];
        }
    }

    public void Add(T value)
    {
        var tail = (_head + _count) % _values.Length;
        if (_count < _values.Length)
            _count++; // was not yet filled to capacity.
        else
            _head = (_head + 1) % _values.Length; // remove oldest.
        _values[tail] = value;
    }

    public T Min 
    {
        get { return Enumerate().Min(); }
    }

    public T Max
    {
        get { return Enumerate().Max(); }
    }

    public IEnumerable<T> Enumerate()
    {
        // enumerates oldest to newest.
        for (var i = 0; i < _count; i++)
            yield return _values[(_head + i) % _values.Length];
    }

    public void RewindBy(int num)
    {
        // Goes back in history, by removing the 'num'
        // most recent values.
        _count = Math.Max(0, _count - num);
    }
}

答案 2 :(得分:0)

我最终在这些阵列上使用常规数组和复制方法来实现所需的功能