← Назад к вопросам

Какая алгоритмическая сложность у Linked List?

1.0 Junior🔥 211 комментариев
#Коллекции и структуры данных

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Алгоритмическая сложность операций Linked List

Связный список (Linked List) — это фундаментальная структура данных, состоящая из узлов (nodes), каждый из которых содержит значение (value/data) и указатель (pointer/reference) на следующий узел. В двусвязном списке (Doubly Linked List) узлы также содержат указатель на предыдущий узел. Сложность операций существенно зависит от типа доступа и конкретной реализации.

Временная сложность основных операций

1. Доступ по индексу (Access by Index)

  • В среднем и худшем случае: O(n)
  • В отличие от массива, где доступ по индексу происходит за O(1), в связном списке необходимо последовательно пройти от головного узла (head) до нужного индекса.
func getNode(at index: Int) -> Node? {
    guard index >= 0 else { return nil }
    var current = head
    var currentIndex = 0
    while current != nil && currentIndex < index {
        current = current?.next
        currentIndex += 1
    }
    return current // Достигли нужного индекса или конца списка
}

2. Поиск элемента (Search)

  • В среднем и худшем случае: O(n)
  • Требуется последовательный обход списка до нахождения элемента или до конца.
func contains(value: Int) -> Bool {
    var current = head
    while let node = current {
        if node.value == value {
            return true
        }
        current = node.next
    }
    return false
}

3. Вставка (Insertion)

  • В начало списка (prepend): O(1) — создаем новый узел и обновляем указатель head.
func prepend(value: Int) {
    let newNode = Node(value: value)
    newNode.next = head
    head = newNode
}
  • В конец списка (append): O(1) если храним указатель на tail, иначе O(n) для поиска последнего узла.
  • В произвольную позицию по индексу: O(n) из-за необходимости найти позицию для вставки, но сама вставка за O(1) после нахождения узла.

4. Удаление (Deletion)

  • Удаление из начала: O(1) — обновляем указатель head.
  • Удаление из конца: O(1) если есть tail и двусвязный список, иначе O(n) для поиска предпоследнего узла.
  • Удаление по значению или индексу: O(n) из-за поиска элемента, но само удаление за O(1) после нахождения.

Пространственная сложность

  • O(n), где n — количество элементов. Каждый узел требует памяти для хранения значения и одного или двух указателей (в зависимости от типа списка).

Сравнение с массивом (Array) в контексте iOS

  • Массив обеспечивает быстрый доступ O(1) по индексу, но вставка/удаление в начале или середине может потребовать O(n) из-за сдвига элементов.
  • Связный список эффективен для частых вставок/удалений в начале, но неэффективен для произвольного доступа.

Практическое применение в iOS разработке

  • История навигации в UINavigationController можно представить как стек (реализуемый через список).
  • Управление памятью в Automatic Reference Counting (ARC) иногда использует подобные структуры для отслеживания ссылок.
  • Кастомные коллекции, где важна эффективная вставка/удаление, а не доступ по индексу.

Оптимизации

  • Двусвязный список упрощает удаление из конца и обход в обратном порядке, но увеличивает расход памяти на хранение дополнительного указателя.
  • Кольцевой связный список (Circular Linked List) позволяет циклически обходить элементы, полезно для реализации ротационных буферов.

Пример использования в Swift

class Node<T> {
    var value: T
    var next: Node?
    
    init(value: T, next: Node? = nil) {
        self.value = value
        self.next = next
    }
}

struct LinkedList<T> {
    var head: Node<T>?
    var tail: Node<T>?
    
    mutating func append(_ value: T) {
        let newNode = Node(value: value)
        if let tailNode = tail {
            tailNode.next = newNode
        } else {
            head = newNode
        }
        tail = newNode
    }
}

Вывод

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

Какая алгоритмическая сложность у Linked List? | PrepBro