Ответ
Амортизированная сложность O(1).
- Если в буфере (
Array,Data,ContiguousArray) достаточно емкости (capacity), операцияappend(_:)выполняется за константное время. - Если места нет, происходит реаллокация с выделением большего блока памяти и копированием всех существующих элементов — операция O(n). Однако стратегия роста емкости (обычно удвоение) делает такие дорогостоящие операции редкими, обеспечивая амортизированную O(1).
Пример:
var buffer = [1, 2, 3] // Начальная емкость может быть 3 или больше
buffer.append(4) // O(1), если capacity >= 4
Нюансы:
ContiguousArrayгарантирует O(1) дляappend, когда есть свободная емкость, так как элементы хранятся в непрерывной области памяти.Dataведет себя аналогичноArray.- Для буферов фиксированного размера (например,
UnsafeMutableBufferPointer) операция добавления не предусмотрена — требуется ручное управление памятью.
Ответ 18+ 🔞
Да ты посмотри, какой прикол, блядь! Вот берёшь ты массив, и кажется, что добавить в него элемент — это всегда быстро, да? Ну типа O(1) и всё такое.
А на самом деле, ёпта, тут целая наука, блядь!
Смотри, если у твоего буфера (ну, Array, Data, ContiguousArray) в загашнике ещё место есть — то есть capacity позволяет — то операция append(_:) и правда отрабатывает за константное время. Быстрёхонько, чик-чик и вставил. Красота!
Но! Вот этот самый «но» всегда вылезает, как геморрой в пятницу перед вылетом в отпуск. Если места-то нет, сука, начинается цирк! Система берёт, находит кусок памяти побольше, и начинает тупо, в лоб, копировать туда все твои старые элементы. Это уже, ясень пень, O(n), то есть чем больше массив, тем дольше копирование, всё логично.
Так в чём же фокус, спросишь ты? А фокус в том, что эта ёбанная стратегия роста — обычно ёмкость просто удваивают — делает такие пиздецово дорогие операции копирования редкими гостями. Получается, что в среднем, если считать по всем операциям добавления, стоимость всё равно выходит константной. Вот это и есть «амортизированная O(1)». Хитро, да? Как будто ты платишь за дорогой ужин не сразу, а по чуть-чуть с каждой зарплаты.
Пример, чтобы совсем понятно стало:
var buffer = [1, 2, 3] // Начальная ёмкость может быть 3 или больше (тут уже хитрый компилятор постарался)
buffer.append(4) // O(1), если capacity >= 4. То есть если места хватило, то всё ок.
А теперь нюансы, блядь, куда же без них:
ContiguousArray— этот товарищ вообще молодец. Он гарантирует O(1) дляappend, когда есть свободная ёмкость, потому что хранит всё в одной непрерывной куче памяти, без лишних телодвижений. Прямолинейный как лом.Data— ведёт себя примерно так же, как и обычныйArray, ничего особенного.- А вот если ты работаешь с буферами фиксированного размера (ну, типа
UnsafeMutableBufferPointer), то тут, дружок, всё, приехали. Тут операцииappendпросто нет в природе. Придётся самому, как обезьяна с гранатой, ручками управлять памятью, следить, чтобы не вылезти за границы, иначе — краш, пиздец и отладка до утра. Так что с такими штуками осторожнее, ебать!