Коллекция Stack<T>
реализует принцип LIFO (Last In, First Out - последним пришел, первым вышел). Основные операции:
Push
- добавление элемента на вершину стекаPop
- извлечение элемента с вершиныPeek
- просмотр верхнего элемента без извлеченияВ .NET Stack<T>
использует массив для хранения элементов и отслеживает вершину стека через индекс:
private T[] _array; // Внутренний массив
private int _size; // Текущее количество элементов
private int _version; // Для контроля изменений при итерации
public void Push(T item)
{
if (_size == _array.Length)
{
Grow(_size + 1); // Увеличение массива
}
_array[_size] = item;
_size++;
_version++;
}
Метод Grow
реализует стратегию увеличения массива:
private void Grow(int capacity)
{
int newCapacity = _array.Length == 0 ? 4 : _array.Length * 2;
Array.Resize(ref _array, newCapacity);
}
public T Pop()
{
if (_size == 0)
throw new InvalidOperationException("Stack empty");
_version++;
T item = _array[_size - 1];
_array[_size - 1] = default!; // Для сборщика мусора
_size--;
return item;
}
public T Peek()
{
if (_size == 0)
throw new InvalidOperationException("Stack empty");
return _array[_size - 1];
}
foreach
используется структура, а не классpublic struct Enumerator : IEnumerator<T>
{
private readonly Stack<T> _stack;
private int _index;
public T Current { get; }
// Реализация интерфейса IEnumerator
}
Пул массивов в .NET 6+:
ArrayPool<T>
Thread Safety:
Теоретически возможна реализация через узлы:
private class Node<T>
{
public T Value;
public Node<T> Next;
}
private Node<T> _head;
Но в .NET выбрана реализация на массиве как более эффективная по:
В System.Collections.Immutable
есть версия на связных списках:
public sealed class ImmutableStack<T>
{
private readonly T _head;
private readonly ImmutableStack<T> _tail;
}
Операция | Сложность | Примечания |
---|---|---|
Push | O(1)* | *Амортизированная при росте массива |
Pop | O(1) | Прямой доступ по индексу |
Peek | O(1) | Прямой доступ по индексу |
Contains | O(n) | Линейный поиск по массиву |
Stack<T>
в .NET использует массив с динамическим расширением, обеспечивая амортизированную O(1) сложность основных операций. Реализация оптимизирована для производительности через структурные энумераторы и эффективное управление памятью.