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

Какая алгоритмическая сложность вставки в середину односвязного списка?

1.2 Junior🔥 81 комментариев
#Коллекции и структуры данных#Язык Swift

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

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

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

Алгоритмическая сложность вставки в середину односвязного списка

Вставка нового элемента в середину односвязного списка имеет алгоритмическую сложность O(n), где n — количество элементов в списке. Это связано с самой структурой односвязного списка и необходимостью найти позицию для вставки.

Почему O(n)?

В односвязном списке каждый элемент (узол) содержит:

  • Данные
  • Ссылку (next) на следующий элемент

Список не предоставляет прямого доступа к элементам по индексу, как это делает массив. Для вставки в середину необходимо:

Шаги алгоритма:

  1. Найти узол, который будет предшествовать новому узлу (предыдущий узол).
  2. Создать новый узол с данными.
  3. Переставить ссылки: новый узол ссылается на следующий после предыдущего, а предыдущий теперь ссылается на новый.

Поиск предыдущего узла требует последовательного прохода от головы списка до нужной позиции. Этот проход — операция с линейной сложностью.

Пример кода и анализ

Рассмотрим реализацию вставки в односвязный список на языке Swift:

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

class SinglyLinkedList<T> {
    var head: Node<T>?
    
    func insertAtMiddle(value: T, at index: Int) {
        // Создание нового узла
        let newNode = Node(value: value)
        
        // Если список пуст или вставка в начало
        if head == nil || index == 0 {
            newNode.next = head
            head = newNode
            return
        }
        
        // Поиск предыдущего узла
        var current = head
        var currentIndex = 0
        while current != nil && currentIndex < index - 1 {
            current = current?.next
            currentIndex += 1
        }
        
        // Если найден предыдущий узол
        if let previous = current {
            newNode.next = previous.next
            previous.next = newNode
        } else {
            // Если индекс превышает размер списка, вставляем в конец
            // (в реальном коде может быть обработка ошибки)
            var last = head
            while last?.next != nil {
                last = last?.next
            }
            last?.next = newNode
        }
    }
}

Анализ сложности:

  • Поиск позиции: цикл while может пройти до index - 1 шагов. В худшем случае (вставка перед последним элементом) это n-1 операций.
  • Сама вставка: после поиска, перестановка ссылок — константные операции O(1).
  • Итоговая сложность: O(n) определяется поиском, так как он доминирует.

Сравнение с другими структурами данных

  • Массив (Array):

    • Вставка в середину также O(n) из- необходимости сдвига элементов.
    • Но доступ по индексу O(1), что быстрее поиска в списке.
  • Двусвязный список (Doubly Linked List):

    • Вставка в середину тоже O(n) (поиск позиции).
    • Но позволяет более эффективные операции вблизи концов списка.

Практические следствия для iOS разработчика

В iOS разработке понимание сложности операций критично для:

  • Оптимизации производительности UI, особенно в таблицах (UITableView, UICollectionView) с большим количеством данных.
  • Выбора структуры данных:
    • Если частые вставки в середину и список большой, односвязный список может быть неэффективным.
    • Альтернативы: использование массивов с резервированием памяти, двусвязных списков или даже других структур (например, прыгающих списков для балансировки).

Вывод: вставка в середину односвязного списка имеет линейную сложность O(n) из- необходимости линейного поиска позиции. Это фундаментальное ограничение структуры, которое важно учитывать при проектировании алгоритмов и выборе коллекций в Swift.

Какая алгоритмическая сложность вставки в середину односвязного списка? | PrepBro