[Алгоритмы, Swift] Linked List: Когда нужно писать свой Copy-on-write в iOS?
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Я всегда думал: "А зачем нужно писать свой copy-on-write? Ведь круто, когда есть структуры и они такие быстрые, что всё делают за тебя."Но все это не нужно, пока не начинаешь писать свои типы и не подсаживаешься на LinkedList'ы.Что такое этот связанный список и какие у него преимущества?Связанный список имеет несколько теоретических преимуществ по сравнению с вариантами непрерывного хранения, такими как Array:
- Связанные списки имеют временную сложность O (1) для вставки первых элементов. Массивы же имеют временную сложность O (n).
- Соответствие протоколам сбора Swift, таким как Sequence и Collection, предлагает множество полезных методов для довольно небольшого количества требований.
Связанный список (Linked List) - это последовательность элементов данных, в которой каждый элемент называется узлом (Node).Есть два основных типа связанных списков:Односвязные списки - это связанные списки, в которых каждый узел имеет ссылку только на следующий узел.
Двусвязные списки - это связанные списки, в которых каждый узел имеет ссылку на предыдущий и следующий узел.
Вам нужно отслеживать, где список начинается и где заканчивается. Обычно это делается с помощью указателей, называемых head и tail.Вот так это всё выглядит:
public class Node<Value> {
public var value: Value
public var next: Node?
public init(value: Value, next: Node? = nil) {
self.value = value
self.next = next
}
}
public struct LinkedList<Value> {
public var head: Node<Value>?
public var tail: Node<Value>?
public init() {}
public var isEmpty: Bool { head == nil }
}
Вау, прикольная структура данных! Она знает и предыдущий, и следующий элемент. Также в списке мы быстро можем добавить. Но есть проблема.Так как наша Node'a является классом, а значит и reference type. Это значит, что для многих узлов у нас есть общая ячейка памяти и куча ссылок на них. Они могут расти и с большими размера за ними сложно наблюдать.Как решить эту проблему? Поскольку LinkedList является структурой и поэтому должен использовать семантику значений. Внедрение своего COW решит эту проблему.Сделать value type значений с помощью COW довольно просто. Прежде чем изменять содержимое связанного списка, вы хотим создать копию базового хранилища и обновить все ссылки (начальные и конечные) на новую копию.
private mutating func copyNodes() {
guard var oldNode = head else {
return
}
head = Node(value: oldNode.value)
var newNode = head
while let nextOldNode = oldNode.next {
newNode!.next = Node(value: nextOldNode.value)
newNode = newNode!.next
oldNode = nextOldNode
}
tail = newNode
}
Этот метод заменит существующие узлы связанного списка вновь выделенными узлами с тем же значением. Здесь всё очень круто, кроме введения накладных расходов O (n) на каждый вызов изменения…Оптимизируем COWНакладные расходы O (n) при каждом вызове изменения недопустимы. Есть два пути, которые помогают решить эту проблему. Первый - избегать копирования, когда у узлов только один владелец.isKnownUniquelyReferenced В стандартной библиотеке Swift существует функция isKnownUniquelyReferenced. Эта функция может использоваться, чтобы определить, имеет ли объект ровно одну ссылку на него. И если добавить в начало функции copyNodes() код, то копировать дальше не надо:
private mutating func copyNodes(returningCopyOf node:
Node<Value>?) -> Node<Value>? {
guard !isKnownUniquelyReferenced(&head) else {
return nil
}
guard var oldNode = head else {
return nil
}
head = Node(value: oldNode.value)
var newNode = head
var nodeCopy: Node<Value>?
while let nextOldNode = oldNode.next {
if oldNode === node {
nodeCopy = newNode
}
newNode!.next = Node(value: nextOldNode.value)
newNode = newNode!.next
oldNode = nextOldNode
}
return nodeCopy
}
Этот метод имеет много общего с предыдущей реализацией. Основное отличие состоит в том, что он вернет вновь скопированный узел на основе переданного параметра.Таким образом Copy-on-write не является чем-то далеким и подкапотным. А вполне управляемым и понятным.
===========
Источник:
habr.com
===========
Похожие новости:
- [Занимательные задачки, Алгоритмы, Сжатие данных] Кодирование для чайников, ч.1
- [Data Mining, Алгоритмы, Математика, Научно-популярное] Звездный год (365 дней 369 минут), Тропический год(+ 348.5 минут) и звездные сутки(1436 минут) в радиоактивном распаде
- [Python, Программирование, Data Mining, Алгоритмы, Машинное обучение] ИИ итоги уходящего 2020-го года в мире машинного обучения
- [Алгоритмы, Математика, DIY или Сделай сам] Математически оптимальные рождественские печеньки (перевод)
- [Алгоритмы, Математика] Рекурсивный алгоритм представления Цекендорфа
- [Занимательные задачки, Программирование, Алгоритмы, Компиляторы] Чемпионат по выполнению теста Кнута
- [Разработка под iOS, Разработка мобильных приложений, Разработка под Android, Тестирование мобильных приложений] 3 видео для мобильного разработчика
- [Программирование, Алгоритмы, Компиляторы, Софт] О реализации точного представления чисел или «где хранить деньги?»
- [Open source, Алгоритмы, Lua, Параллельное программирование] Такие важные короткоживущие данные
- [Алгоритмы, Обработка изображений, Машинное обучение] Эксперимент в распознавании рукописных текстов на кириллице. Часть 2
Теги для поиска: #_algoritmy (Алгоритмы), #_swift, #_linkedlist, #_algoritmy (
Алгоритмы
), #_swift
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 15:47
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Я всегда думал: "А зачем нужно писать свой copy-on-write? Ведь круто, когда есть структуры и они такие быстрые, что всё делают за тебя."Но все это не нужно, пока не начинаешь писать свои типы и не подсаживаешься на LinkedList'ы.Что такое этот связанный список и какие у него преимущества?Связанный список имеет несколько теоретических преимуществ по сравнению с вариантами непрерывного хранения, такими как Array:
Двусвязные списки - это связанные списки, в которых каждый узел имеет ссылку на предыдущий и следующий узел. Вам нужно отслеживать, где список начинается и где заканчивается. Обычно это делается с помощью указателей, называемых head и tail.Вот так это всё выглядит: public class Node<Value> {
public var value: Value public var next: Node? public init(value: Value, next: Node? = nil) { self.value = value self.next = next } } public struct LinkedList<Value> { public var head: Node<Value>? public var tail: Node<Value>? public init() {} public var isEmpty: Bool { head == nil } } private mutating func copyNodes() {
guard var oldNode = head else { return } head = Node(value: oldNode.value) var newNode = head while let nextOldNode = oldNode.next { newNode!.next = Node(value: nextOldNode.value) newNode = newNode!.next oldNode = nextOldNode } tail = newNode } private mutating func copyNodes(returningCopyOf node:
Node<Value>?) -> Node<Value>? { guard !isKnownUniquelyReferenced(&head) else { return nil } guard var oldNode = head else { return nil } head = Node(value: oldNode.value) var newNode = head var nodeCopy: Node<Value>? while let nextOldNode = oldNode.next { if oldNode === node { nodeCopy = newNode } newNode!.next = Node(value: nextOldNode.value) newNode = newNode!.next oldNode = nextOldNode } return nodeCopy } =========== Источник: habr.com =========== Похожие новости:
Алгоритмы ), #_swift |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 15:47
Часовой пояс: UTC + 5