如何移动元素
本文关键字:元素 移动 何移动 | 更新日期: 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}
背景信息:
我正在将样本推送到缓冲区。缓冲器基本上是一长串样本上的滑动窗口。有时我想"倒回"窗口;那就是:把它移回去,因为我推的样本应该被丢弃。我不知道样品是否应该提前丢弃。我必须推样品,对"窗口"内的样品做一些计算,然后决定是否要及时"备份"窗口。
更新要求:
实现一个固定大小的N个元素的缓冲区X。缓冲区中最老的元素位于索引0 (X[0])处。缓冲区中最新的元素位于索引N-1 (X[N-1])
实现一个方法'Write',它将一个样本s写入缓冲区。当一个样本被写入缓冲区时,缓冲区中的样本被移动X [j] = X [j + 1] j = 0 = n - X (n - 1) = s。
在任何给定时间,应该有以下方法可用:
- 查找缓冲区中的最大采样值
- 查找缓冲区中的最小采样值
- 查找缓冲区中样本值的平均值
- 读取缓冲区中任意位置的采样值
"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);
}
}
我最终使用常规数组和这些数组上的复制方法来实现所需的功能