Middle
Какво е по-добре да използвате: ArrayList или LinkedList, ако искам да изтрия елемент от средата на списъка?
sobes.tech AI
Отговор от AI
ArrayList.
При изтриване на елемент от средата на списъка:
- ArrayList: Изисква преместване на всички последващи елементи, което в най-лошия случай (при изтриване на първия елемент) отнема време $O(n)$, където $n$ е броят на елементите. Средно обаче операцията остава $O(n)$, тъй като трябва да се премести само половината от елементите. Фактическата производителност често е по-добра поради по-добрата локализация на данните.
- LinkedList: Изисква итерация през елементите до намиране на необходимия възел ($O(n)$ в най-лошия случай, ако започва от началото или края). След намиране на възела, изтриването отнема $O(1)$.
Въпреки че самото изтриване на възела в LinkedList е по-бързо, търсенето на възела преди изтриването прави цялостната операция средно по-бавна, отколкото в ArrayList.
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class ListRemovalComparison {
public static void main(String[] args) {
int size = 100000; // Размер на списъка
int removeIndex = size / 2; // Индекс за изтриване (средата)
// ArrayList
List<Integer> arrayList = new ArrayList<>();
for (int i = 0; i < size; i++) {
arrayList.add(i);
}
long startTimeArrayList = System.nanoTime();
arrayList.remove(removeIndex); // Изтриване от средата
long endTimeArrayList = System.nanoTime();
long durationArrayList = (endTimeArrayList - startTimeArrayList);
System.out.println("Време за изтриване от ArrayList: " + durationArrayList + " ns");
// LinkedList
List<Integer> linkedList = new LinkedList<>();
for (int i = 0; i < size; i++) {
linkedList.add(i);
}
long startTimeLinkedList = System.nanoTime();
linkedList.remove(removeIndex); // Изтриване от средата
long endTimeLinkedList = System.nanoTime();
long durationLinkedList = (endTimeLinkedList - startTimeLinkedList);
System.out.println("Време за изтриване от LinkedList: " + durationLinkedList + " ns");
}
}
Резултатите показват, че при изтриване на елемент от средата, ArrayList обикновено е по-бърз, въпреки теоретичната сложност на преместването. Това се дължи на факта, че търсенето по индекс в LinkedList ($O(n)$) е по-бавно, отколкото преместването в ArrayList.
// ArrayList - достъп по индекс O(1), изтриване O(n) (преместване)
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("A");
arrayList.add("B");
arrayList.add("C");
arrayList.remove(1); // Изтриване на "B" - преместване на "C"
// LinkedList - достъп по индекс O(n), изтриване O(1) (след намиране на възела)
LinkedList<String> linkedList = new LinkedList<>();
linkedList.add("A");
linkedList.add("B");
linkedList.add("C");
linkedList.remove(1); // Изтриване на "B" - първо трябва да се намери възелът "B" (O(n)), след това да се изтрие (O(1))
В крайна сметка, за операцията изтриване от средата, ако знаете индекса, ArrayList често е по-подходящ избор поради по-бързата операция за достъп по индекс, което компенсира разходите за преместване.