← Назад к вопросам
Какая временная сложность update в связном списке?
1.3 Junior🔥 151 комментариев
#Dart
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Какая временная сложность update в связном списке
Временная сложность операции обновления (изменение значения) в связном списке зависит от того, известна ли позиция элемента. В Dart связные списки реализованы классом LinkedList.
Временная сложность по типам операций
1. Update, если знаем узел (Node) — O(1)
Если у нас есть прямая ссылка на узел, обновление происходит мгновенно:
// ✅ O(1) — прямой доступ к узлу
node.value = newValue;
2. Update по индексу — O(n)
Если нужно найти элемент по индексу, нужно пройти от начала:
class LinkedListExample {
LinkedList<int> list = LinkedList<int>();
// O(n) — нужно пройти от начала до позиции
void updateAtIndex(int index, int newValue) {
var current = list.first;
for (int i = 0; i < index; i++) {
current = current.next as LinkedListEntry<int>;
}
current.value = newValue; // O(1) сама операция, но поиск O(n)
}
}
3. Update по значению — O(n)
Если ищем элемент по значению:
// O(n) — нужно пройти весь список в худшем случае
void updateByValue(int oldValue, int newValue) {
for (var node in list) {
if (node.value == oldValue) {
node.value = newValue;
break;
}
}
}
Полная таблица сложности LinkedList
Операция | Сложность | Описание
------------------|-----------|----------------------------
Access (к узлу) | O(1) | Если есть ссылка на узел
Access (по индексу)| O(n) | Нужно найти с начала
insert (в начало) | O(1) | Вставка перед first
insert (в конец) | O(1) | Вставка после last
insert (в позицию) | O(n) | Нужно найти позицию
delete (узел) | O(1) | Если есть ссылка
delete (по индексу)| O(n) | Нужно найти узел
update (узел) | O(1) | Если есть ссылка
update (по индексу)| O(n) | Нужно найти узел
search | O(n) | Линейный поиск
Практические примеры в Dart
Пример 1: O(1) update с известным узлом
class LinkedListNode<T> {
T value;
LinkedListNode(this.value);
}
class LinkedListExample {
late LinkedListEntry<int> _nodeToUpdate;
LinkedList<int> list = LinkedList<int>();
void initWithNode() {
_nodeToUpdate = LinkedListEntry(42);
list.add(_nodeToUpdate);
}
// O(1) — прямой доступ к сохранённому узлу
void quickUpdate(int newValue) {
_nodeToUpdate.value = newValue;
}
}
Пример 2: O(n) update по индексу
class LinkedList<T> {
LinkedListEntry<T>? first;
// O(n) — нужно пройти список
void updateAtIndex(int index, T newValue) {
var current = first;
for (int i = 0; i < index && current != null; i++) {
current = current.next as LinkedListEntry<T>?;
}
if (current != null) {
current.value = newValue;
}
}
}
Пример 3: Оптимизация — список с Map кешем
class OptimizedLinkedList<T> {
LinkedList<T> _list = LinkedList<T>();
Map<String, LinkedListEntry<T>> _indexMap = {}; // Кеш для быстрого доступа
// O(1) благодаря кешу
void updateFast(String key, T newValue) {
var node = _indexMap[key];
if (node != null) {
node.value = newValue;
}
}
// O(n) для первого добавления
void addWithKey(String key, T value) {
var node = LinkedListEntry(value);
_list.add(node);
_indexMap[key] = node;
}
}
Почему это медленнее чем Array
// Array (List) — O(1) update
var array = [1, 2, 3, 4, 5];
array[2] = 99; // O(1) — прямой доступ по индексу
// LinkedList — O(n) update
var linkedList = LinkedList<int>();
// ... добавили элементы ...
// Нужно 3 шага, чтобы дойти до 3-го элемента: O(n)
var current = linkedList.first;
current = current.next;
current = current.next;
current!.value = 99; // Наконец O(1) обновление
Сравнение структур данных
// ✅ List — быстро для update по индексу
var list = [1, 2, 3];
list[1] = 99; // O(1)
// ✅ LinkedList — быстро если есть ссылка на узел
LinkedListEntry<int> node = ...;
node.value = 99; // O(1)
// ✅ Map — быстро для update по ключу
var map = {'key': 1};
map['key'] = 99; // O(1)
// ❌ LinkedList медленно для update по индексу
var linkedList = LinkedList<int>();
// Нужно пройти весь список: O(n)
Когда использовать LinkedList
Частые операции в начале/конце:
// ✅ LinkedList отличен для этого
var queue = LinkedList<String>();
queue.add(LinkedListEntry('first')); // O(1)
queue.addFirst(LinkedListEntry('add')); // O(1)
queue.remove(queue.first); // O(1)
Частые операции в середине:
// ❌ LinkedList медленный
var list = LinkedList<String>();
for (int i = 0; i < 100; i++) {
list.add(LinkedListEntry('item$i'));
}
// Update элемента в середине — O(n)
var node = ...; // Нужно найти узел
node.value = 'updated'; // O(n) для поиска
// ✅ List быстрее
var list = <String>[];
for (int i = 0; i < 100; i++) {
list.add('item$i');
}
list[50] = 'updated'; // O(1)
Итоговый вывод
Update в связном списке:
- O(1) если известна ссылка на узел
- O(n) если нужно найти элемент по индексу или значению
Рекомендация: Используй LinkedList только если часто добавляешь/удаляешь в начале/конце. Для остального лучше обычный List.