Есть ли в Dart встроенная структура данных «стек»?

«Есть ли в Dart встроенная структура данных «стек»?» — вопрос из категории Алгоритмы и структуры данных, который задают на 36% собеседований Flutter Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Специального класса Stack в стандартной библиотеке Dart нет, но его легко и идиоматично реализовать на основе List<T>, используя методы add (для добавления) и removeLast (для извлечения). Это соответствует принципу LIFO (Last In, First Out).

Базовая реализация:

void main() {
  // Использование List как стека
  final stack = <String>[];

  // Push (добавление)
  stack.add('Task 1');
  stack.add('Task 2');
  print(stack); // [Task 1, Task 2]

  // Peek (посмотреть верхний элемент)
  final top = stack.last; // 'Task 2'

  // Pop (извлечение)
  final popped = stack.removeLast(); // 'Task 2'
  print(stack); // [Task 1]
}

Для частого использования удобно создать класс-обертку:

class Stack<T> {
  final List<T> _storage = [];

  void push(T element) => _storage.add(element);
  T pop() => _storage.removeLast();
  T get peek => _storage.last;
  bool get isEmpty => _storage.isEmpty;
  bool get isNotEmpty => _storage.isNotEmpty;
  int get length => _storage.length;

  @override
  String toString() => 'Stack(${_storage.reversed.join(' <- ')})';
}

// Пример использования
final historyStack = Stack<String>();
historyStack.push('/home');
historyStack.push('/settings');
print(historyStack.pop()); // /settings
print(historyStack.peek); // /home

Типичные сценарии использования в разработке на Flutter:

  • Навигация: Управление историей маршрутов (хотя Navigator делает это сам).
  • Отмена действий (Undo): Хранение состояний для возможности отката.
  • Алгоритмы: Обход деревьев (например, виджет-дерева для кастомных инспекторов), парсинг выражений, проверка сбалансированности скобок.