Ответ довольно поздний, но я пишу его для будущих читателей
List<T>
- это именно то, что вам нужно, но он имеет большой недостаток по сравнению с Queue<T>
: он реализован с массивом, тогда Dequeue()
довольно дорогой (с точки зрения времени), потому что все элементы должны быть сдвинуты на один шаг обратно с Array.Copy
. Даже Queue<T>
использует массив, но вместе с двумя индексами (для головы и хвоста).
В вашем случае вам также понадобится Remove
/ RemoveAt
, и его производительность не будет хорошей (по той же причине: если вы не удаляете из хвоста списка, тогда должен быть выделен другой массив и скопированы элементы).
Лучшая структура данных для быстрого Dequeue
/ Remove
времени - это связанный список (вы немного пожертвуете производительностью для Enqueue
, но при условии, что ваша очередь имеет равное число Enqueue
/ Dequeue
операций у вас будет большой прирост производительности, особенно когда его размер будет расти).
Давайте рассмотрим простой скелет для его реализации (я пропущу реализацию для IEnumerable<T>
, IList<T>
и других вспомогательных методов).
class LinkedQueue<T>
{
public int Count
{
get { return _items.Count; }
}
public void Enqueue(T item)
{
_items.AddLast(item);
}
public T Dequeue()
{
if (_items.First == null)
throw new InvalidOperationException("...");
var item = _items.First.Value;
_items.RemoveFirst();
return item;
}
public void Remove(T item)
{
_items.Remove(item);
}
public void RemoveAt(int index)
{
Remove(_items.Skip(index).First());
}
private LinkedList<T> _items = new LinkedList<T>();
}
Для быстрого сравнения:
Queue List LinkedList
Enqueue O(1)/O(n)* O(1)/O(n)* O(1)
Dequeue O(1) O(n) O(1)
Remove n/a O(n) O(n)
* O (1) - это типичный случай, но иногда это будет O (n) (когда необходимо изменить размер внутреннего массива).
Конечно, вы заплатите что-то за то, что получаете: использование памяти больше (особенно для небольших T
накладных расходов будет здорово). Правильная реализация (List<T>
против LinkedList<T>
) должна быть тщательно выбрана в соответствии с вашим сценарием использования, вы также можете преобразовать этот код в единый связанный список, чтобы уменьшить 50% накладных расходов памяти.