如何获取队列中的第一个和最后一个元素?

16

假设我有一个连续的值的集合,我指定了集合的大小,每当添加新值时,超过指定大小的旧值都会被删除。显然(我已经测试过)最适合这种行为的集合类型是队列(Queue):

myQueue.Enqueue(newValue)
If myQueue.Count > specifiedSize Then myQueue.Dequeue()

然而,如果我想计算队列中第一个和最后一个项目之间的差异怎么办?显然,我不能通过索引访问项目。但是从队列切换到实现IList的东西似乎有些大材小用,编写一个新的类似于队列的类也是如此。现在我的代码是:

Dim firstValue As Integer = myQueue.Peek()
Dim lastValue As Integer = myQueue.ToArray()(myQueue.Count - 1)
Dim diff As Integer = lastValue - firstValue

调用ToArray()让我感到不安,但我想不出更好的替代方案。有什么建议吗?


C# 没有 Dequeue 类型吗? - Thom Smith
不,C#本身没有类型,.Net才有类型;而且 .Net 没有 Dequeue 类型,它有一个 Queue/Queue<T> 类型,该类型具有 Dequeue 方法。 - Rafa Castaneda
5个回答

27

你可以做的一件事是创建一个临时变量,用来存储最近入队的值,因为它将是最后一个值,所以可以访问该变量以获取该值。


大约在你提供这个答案的同时,我意识到解决方案(基本上就是你建议的)是多么简单明了。真是个好主意! - Dan Tao

18

如果你需要快速访问列表中的第一个项目,那么你可能正在使用错误的数据结构。改用LinkedList,它有方便的First和Last属性。

确保仅使用AddLast和RemoveFirst向链接列表添加和删除项以维护队列属性。为了防止意外违反队列属性,请考虑创建一个包装类来包装链接列表,并仅公开您从队列中需要的属性。


不幸的是,这比在数据结构本身之外跟踪最后添加的方式要好。 - Dark Castle

10
public class LastQ<T> : Queue<T>
{
    public T Last { get; private set; }

    public new void Enqueue(T item)
    {
         Last = item;
         base.Enqueue(item);
    }
}

编辑: 显然,这个基本类应该更加健壮,以执行诸如在空队列上保护Last属性之类的操作。但是,这应该足够了解基本思想。


哈!这几乎是我刚写的代码,只有类名和我在base.Enqueue(item)之后加了Last = item的区别。 - Dan Tao
当最后一个元素被移除时会发生什么?你如何将“Last”设置为倒数第二个元素? - nawfal

3

您最好的选择是跟踪添加到队列中的最后一个值,然后使用myQueue.Peek()函数查看列表中的“第一个”(即下一个)项,而不将其删除。


3
您可以使用双端队列(deque)。我认为System.Collections(.Generic)中没有内置的双端队列,但以下是有关数据结构的一些信息。如果您实现了类似于此的内容,则可以使用PeekLeft()和PeekRight()获取第一个和最后一个值。
当然,您可以自己决定是实现自己的deque还是处理ToArray()的不美观性。 :) http://www.codeproject.com/KB/recipes/deque.aspx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接