如何移动数组中的项目?

时间:2020-03-06 14:52:30  来源:igfitidea点击:

我有一系列对时间敏感的物品。一段时间后,最后一个项目需要掉落,并在开始处放置一个新项目。

做这个的最好方式是什么?

解决方案

请改用队列。

通过使用队列,最好是使用链表实现的队列。

我建议使用队列,只是一个数组或者列表的特殊实例。当定时事件发生时,从队列中弹出最后一个项目,然后将新项目压入。

看一下使用队列而不是简单的数组。

如果有固定数量的项目,则队列将起作用。

给定"时间量",知道如何使用带DateTime键的SortedDictionary并重写Add方法以删除所有键过旧的项。

LinkedList <T>具有应完美运行的AddFirst和RemoveLast成员。

编辑:看队列文档,似乎他们使用内部数组。只要实现使用圆形数组类型算法,性能就应该不错。

在csharp 3中,我们可以执行以下操作:

original = new[] { newItem }.Concat(
    original.Take(original.Count() - 1)).ToArray()

但是我们最好使用专门的数据结构

Queue非常适合FIFO阵列。对于通用数组处理,请使用List(T)
例如," Insert(0,x)"和" RemoveAt(0)"方法可将项目放置或者删除列表前面的内容。

使用数组执行此操作的最简单方法可能是使用循环索引。而不是始终查看array [n],我们可以引用array [cIndex](其中cIndex引用要索引的数组中的项目(cIndex根据arraySize(cIndex%arraySize)递增)。

当选择阵列中删除最旧的项目,则只需引用位于((CINDEX +(ARRAYSIZE 1))%ARRAYSIZE)的元素。

或者,我们可以使用linkedList方法。

从技术上讲,我们需要双端队列。队列中只有一端推送和弹出的项目。两端的双端队列是开放的。

大多数语言都允许数组操作,只需删除第一个元素,然后在最后一个元素。

或者,我们可以通过循环移动每个元素。只需将每个元素(从最旧的元素开始)替换为其相邻元素即可。然后将新项目放在最后一个元素中。

如果我们知道双端队列的大小不会超过一定大小,则可以使其为圆形。我们将需要两个指针来告诉我们两端在哪里。添加和删​​除项目将相应地增加/减少指针。我们必须检测缓冲区溢出情况(即,指针"交叉")。而且,我们将必须使用模块化算术,以便指针绕着数组绕一圈。

或者,我们可以为数组中的每个元素添加时间戳,并在它们变得"太旧"时将其删除。我们可以通过以相同的方式对单独的数组进行索引,或者通过将两个元素数组组成一个数组并将时间戳存储在子元素之一中来实现此目的。

如果我们正在寻找执行此操作的最快方法,那么它将是一个圆形数组:我们要跟踪数组中的当前位置(ndx)和数组的末尾(end),因此当我们插入一个项目,则隐式消除最旧的项目。

循环数组是我所知道的最快的固定大小队列的实现。

例如,在C / C ++中,int看起来像这样(当我们得到0时退出):

int queue[SIZE];
int ndx=0;      // start at the beginning of the array
int end=SIZE-1;
int newitem;
while(1){
  cin >> newitem;
  if(!newitem)  // quit if it's a 0
    break;
  if(ndx>end)   // need to loop around the end of the array
    ndx=0;
  queue[ndx] = newitem;
  ndx++
}

可以进行很多优化,但是如果我们想自己构建它,这是最快的方法。

如果我们不关心性能,请使用附带的Queue对象,因为它应该被概括化。

它可能会或者可能不会进行优化,并且可能不支持固定大小的列表,因此请务必在使用前检查其文档。