В чем разница между связным списком и массивом (списком)?

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

Ответ

В Dart базовой структурой является List, который является реализацией динамического массива, а не связного списка.

Аспект Массив / List (Dart) Связный список (реализация вручную)
Хранение Элементы в непрерывном блоке памяти. Элементы (узлы) разбросаны в памяти, каждый хранит значение и ссылку на следующий узел.
Доступ по индексу O(1) — мгновенный. O(n) — требуется перебор от начала списка.
Вставка/удаление в начале O(n) — требует сдвига всех элементов. O(1) — меняется только ссылка в голове списка.
Вставка/удаление в середине O(n) — сдвиг части элементов. O(1) — если известен предыдущий узел, иначе O(n) на поиск.
Использование в Dart Встроенный тип List. Повсеместно используется. Нет встроенной реализации. Создается вручную для специфических задач.

Пример реализации односвязного списка на Dart:

class Node<T> {
  T value;
  Node<T>? next;
  Node(this.value);
}

class LinkedList<T> {
  Node<T>? head;

  void addToFront(T value) {
    final newNode = Node(value);
    newNode.next = head; // O(1) вставка в начало
    head = newNode;
  }

  T? elementAt(int index) { // O(n) доступ по индексу
    Node<T>? current = head;
    int currentIndex = 0;
    while (current != null && currentIndex < index) {
      current = current.next;
      currentIndex++;
    }
    return current?.value;
  }
}

// Сравнение с List
void main() {
  // Массив (List)
  List<int> myList = [10, 20, 30];
  print(myList[1]); // 20 - мгновенный доступ

  // Связный список
  final linkedList = LinkedList<int>();
  linkedList.addToFront(30);
  linkedList.addToFront(20);
  linkedList.addToFront(10); // Порядок: 10 -> 20 -> 30
  print(linkedList.elementAt(1)); // 20 - доступ через перебор
}

В Flutter-разработке List используется в 99% случаев из-за эффективности доступа по индексу и удобства. Связные списки применяются редко, например, для реализации сложных структур данных вроде LRU-кэша.