Как LinkedList добавляет (int, E) сложности O (1)?
Из linked-list tag wiki excerpt
Связанный список - это структура данных, в которой содержатся элементы ссылки на следующий (и, возможно, предыдущий) элемент. связанный списки предлагают O (1) вставку и удаление в любой позиции, список O (1) конкатенация и O (1) доступ спереди (и, возможно, обратно) а также O (1) доступ к следующему элементу. Случайный доступ имеет O (N) сложность и обычно не реализуется.
(акцент мой)
Я был удивлен, прочитав это & ndash; как список может вставляться в случайный индекс с меньшей сложностью, чем просто читать этот индекс?
Итак, я посмотрел исходный код java.util.LinkedList
. Метод add(int, E)
:
public void add(int index, E element) {
addBefore(element, (index==size ? header : entry(index)));
}
Метод addBefore(E, Entry<E>
- это просто переназначение указателя, но также метод entry(int)
:
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException("Index: "+index+
", Size: "+size);
Entry<E> e = header;
if (index < (size >> 1)) {
for (int i = 0; i <= index; i++)
e = e.next;
} else {
for (int i = size; i > index; i--)
e = e.previous;
}
return e;
}
Даже при оптимизации по половинному размеру цикл for
здесь (тот или другой) кажется мне бесполезным, что этот метод (и, следовательно, add(int, E)
) работает в минимальном наихудшем сценарии O (n) и, конечно, не постоянное время.
Что мне не хватает? Неужели я неправильно понимаю обозначение Big-O?
Ответы
Ответ 1
Ну, они поддерживают постоянные вставки в произвольных позициях, но , только если, у вас есть указатель на запись списка, после которой или перед которой вы хотите что-то вставить. Конечно, это не сработает, если у вас есть только индекс, но это не то, что вы обычно делаете в оптимизированном коде.
В Java вы тоже можете это сделать, но использовать только итератор списка.
Это свойство связанных списков является их самым большим преимуществом по сравнению с аррайалистами или около того - например, если вы хотите удалить пользователя из списка пользователей чата, вы можете сохранить указатель на позицию пользователя в списке пользователей в пользователь, так что, когда он хочет покинуть комнату, это может быть реализовано как операция O(1)
.
Ответ 2
Это потому, что статья, которую вы читаете, считается "попаданием в этот индекс" в качестве отдельной операции. В статье предполагается, что вы уже указали индекс, который хотите выполнить add (int, E).
В заключение:
Вставка или удаление операции = O (1)
Поиск node при n th index = O (n)
Ответ 3
Операцией привязки нового node к любому node является O (1), но операция нахождения (помогает в цикле) соответствующий индекс определенно O (n).
Нет волшебства;)
Ответ 4
Процитированная вами страница wiki говорит:
O (1) вставка и удаление в любой позиции
Затем вы спрашиваете:
Я с удивлением прочитал это - как может вставить список в случайный индекс
В этом заключается путаница: положение и индекс терминов не используются, чтобы означать одно и то же. Вики рассказывают об итераторе или указателе, а не об индексе.