Требования к сложности для std :: deque :: push_back / front - PullRequest
11 голосов
/ 01 декабря 2011

В результате этого вопроса от нескольких дней назад есть несколько вещей, которые мешали мне в отношении требований к сложности для std::deque::push_back/push_front против фактических std::deque реализаций в дикой природе.

Результатом предыдущего вопроса было то, что эти операции должны иметь O(1) сложность наихудшего случая. Я подтвердил, что это действительно так в c++11:

из 23.3.3.4 модификаторы deque, вставка, вставка / вставка перед / зад

Сложность: сложность является линейной по количеству вставленных элементов плюс меньшее из расстояний до начала и конца deque. Вставка одного элемент в начале или в конце deque всегда занимает постоянное время и вызывает один вызов конструктора T.

Это сочетается с требованием сложности O(1) для индексации через operator[] и т. Д.

Проблема в том, что реализации не соответствуют этим требованиям.

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

В худшем случае для push_back/front etc может потребоваться выделение дополнительного блока (что хорошо - фиксированное распределение размера O(1)), но также может потребоваться изменение размера динамического массива указателей блоков - это не хорошо, так как это O(m), где m - это количество блоков, которое в конце дня равно O(n).

Очевидно, что это все еще амортизируется O(1) сложность, и, как правило, m << n это будет довольно быстро на практике. Но, кажется, есть проблема с соответствием?

Кроме того, я не вижу, как вы можете спроектировать структуру данных, которая строго удовлетворяет сложности O(1) для push_back/front etc и operator[]. Вы могли бы иметь связанный список указателей блоков, но это не дает желаемого поведения operator[]. Это действительно может быть сделано?

Ответы [ 2 ]

3 голосов
/ 01 декабря 2011

В C ++ 11 FDIS мы можем читать:

23.2.3 Контейнеры последовательности [sequence.reqmts]

16 / В таблице 101 перечислены операции, которые предоставляются для некоторых типов контейнеров последовательностей, но не для других. Реализация должна предоставлять эти операции для всех типов контейнеров, показанных в столбце «контейнер», и должна реализовывать их так, чтобы принимать амортизированное постоянное время .

Где Таблица 101 имеет имя Необязательные последовательности операций контейнера и список deque для операций push_back и push_front.

Поэтому в приведенном вами абзаце это больше похоже на небольшое упущение. Возможно, стоит сообщить о дефекте?

Обратите внимание, что одиночный вызов конструктора по-прежнему сохраняется.

0 голосов
/ 01 декабря 2011

Я подозреваю, что перераспределение указателей блоков выполняется с геометрически увеличивающимся размером - это обычный прием для std :: vector.Я думаю, что технически это O (log m), но, как вы указываете, m << n, так что на практике это не влияет на реальные результаты. </p>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...