Как бы вы получили первый и последний элементы в очереди? - PullRequest
8 голосов
/ 20 августа 2009

Скажем, у меня есть скользящая коллекция значений, в которой я указываю размер коллекции, и каждый раз, когда добавляется новое значение, все старые значения, превышающие указанный размер, отбрасываются. Очевидно (и я проверял это) лучшим типом коллекции для этого поведения является Очередь:

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() беспокоит меня, но лучшая альтернатива мне не подходит. Есть предложения?

Ответы [ 5 ]

16 голосов
/ 20 августа 2009

Одна вещь, которую вы могли бы сделать, это иметь временную переменную, которая хранит значение, которое было только что помещено в очередь, потому что это будет последнее значение, и поэтому к переменной можно получить доступ, чтобы получить это значение.

13 голосов
/ 20 августа 2009

Мне кажется, если вам нужен быстрый доступ к первому элементу в списке, значит, вы используете неправильную структуру данных. Вместо этого переключите LinkedList, который удобно имеет свойства First и Last.

Убедитесь, что вы только добавляете и удаляете элементы в связанный список, используя AddLast и RemoveFirst, чтобы поддерживать свойство Queue. Чтобы не допустить случайного нарушения свойства Queue, рассмотрите возможность создания класса-оболочки вокруг связанного списка и предоставления только тех свойств, которые вам нужны из вашей очереди.

5 голосов
/ 20 августа 2009
public class LastQ<T> : Queue<T>
{
    public T Last { get; private set; }

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

Edit: Очевидно, этот базовый класс должен быть более устойчивым для таких вещей, как защита свойства Last в пустой очереди. Но этого должно быть достаточно для основной идеи.

2 голосов
/ 20 августа 2009

Вы можете использовать деку ( d ouble- e nded очередь ).

Я не думаю, что есть один встроенный в System.Collections (.Generic), но вот некоторая информация о структуре данных. Если вы реализовали что-то подобное, вы могли бы просто использовать PeekLeft () и PeekRight (), чтобы получить первое и последнее значения.

Конечно, вам решать, будет ли реализация вашей собственной очереди предпочтительнее, чем работа с несексуализатором ToArray (). :)

http://www.codeproject.com/KB/recipes/deque.aspx

2 голосов
/ 20 августа 2009

Лучше всего следить за последним значением, добавленным к Queue, а затем использовать функцию myQueue.Peek(), чтобы увидеть «первый» (то есть следующий) элемент в списке, не удаляя его.

...