如何移动元素

本文关键字:元素 移动 何移动 | 更新日期: 2023-09-27 17:54:20

假设你在。net (Systems.Generic.Collections.Queue)中有一个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:两个最近添加的元素被"drop "(倒带)

{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. 实现一个方法'Write',它将一个样本s写入缓冲区。当一个样本被写入缓冲区时,缓冲区中的样本被移动X [j] = X [j + 1] j = 0 = n - X (n - 1) = s。

  3. 在任何给定时间,应该有以下方法可用:

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

我希望以上说明了我想要什么。谢谢。

如何移动元素

因此,鉴于您的新要求,我将实现这个类:

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

这段代码显然只是一个外壳——我把内部工作留给你去编码。

我完全按照你的要求做了。

当前编译的代码应该有助于使它成为一个很好的起点。

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

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

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

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