Вставка Посередине: Arraylist Против Linkedlist

Однажды на собеседовании мне задали вопрос: какая реализация списка быстрее вставится в середину: ArrayList или LinkedList? На первый взгляд вопрос простой — нужно посчитать алгоритмическую сложность каждого варианта и сравнить их.

Вставку в середину можно разделить на две операции: поиск середины списка и саму вставку.

Для ArrayList поиск элемента по индексу не представляет сложности, поскольку элементы списка находятся в массиве.

Алгоритмическая сложность равна O(1).

В случае с LinkedList нам придется последовательно перебирать все элементы, пока не доберемся до нужного элемента.

Сложность будет O(n).

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

В LinkedList вставка заключается в создании нового связывающего объекта и установке ссылок на него в соседних элементах.

Сложность O(1).

В целом сложность вставки в середину ArrayList и LinkedList одинаковая — O(n).

Я показал это рассуждение интервьюеру, на что он задал мне вопрос: «Так что быстрее: пройти по элементам или сдвинуть элементыЭ» Я быстро подсчитал, что операция чтения существенно быстрее операции записи, и сказал, что LinkedList сделает это быстрее.

Придя домой, я задумался над этим вопросом.

Искал решение этой проблемы на форумах.

Кто-то со мной согласился, но многие учли, что операция смещения выполняется родной более быстрый метод, поэтому ArrayList быстрее выполнит вставку в середину.

Не получив однозначного и неопровержимого ответа, я решил провести собственное исследование.

Сначала я углубился в исходный код этих классов.

Вставка элемента в ArrayList происходит так: сначала при необходимости массив увеличивается, затем все элементы, расположенные после точки вставки, смещаются на количество позиций, равное количеству вставленных элементов (я рассматриваю один элемент), и в конце вставленный элемент ставится на место.

Массив увеличивается со скоростью n*1,5, где n — размер массива, а минимальное увеличение при стандартных условиях (емкость=10) составляет 5 элементов.

В связи с этим операцией увеличения массива можно пренебречь при расчете алгоритмической сложности вставки.

Сдвиг элементов после точки вставки имеет алгоритмическую сложность O(n).

Таким образом, общая сложность по-прежнему остается O(n).

Да, мы помним, что операция увеличения массива немного увеличивает сложность, но нативность действий с массивом увеличивает скорость работы.

Поиск элемента в LinkedList начинается в цикле с края списка.

Если искомый элемент находится в первой половине списка, то поиск начинается с начала; иначе, с конца.

Так как мы вставляем ровно посередине, то в цикле пройдем ровно половину элементов.

Сложность O(n).

Сама вставка, как я писал выше, заключается в создании объекта и указании ссылки на него.

Сложность O(1).

Опять же, ничего нового я не обнаружил: общая сложность осталась O(n), при этом учитывая, что создание объекта — «дорогая» операция.

Анализ исходного кода ситуацию не прояснил, поэтому я начал писать тесты.

Я решил исследовать зависимость от двух параметров: исходного размера списка и количества последовательных вставок (количества итераций).

Пример исходного кода

   

package com.jonasasx.liststest; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; public class Main {

Теги: #java #list #arraylist #linkedlist #алгоритмическая сложность #программирование #java #Алгоритмы
Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.