Я могу представить три операции в С++, которые могут быть описаны в некотором смысле как имеющие "постоянную" сложность. Я видел некоторые дебаты (*) по поводу этого, и мне кажется, что мы могли бы просто сказать: "все эти операции постоянны, но некоторые более постоянные, чем другие": -)
( Изменить 2: Если вы уже знаете, что знаете ответ, прочитайте некоторые из этих дебатов по этому вопросу, прежде чем поспешить слишком рано: Какие данные структура, точно, являются deques в С++? Многие люди с довольно высокими баллами спорят о том, что означает "постоянный". Мой вопрос не так очевиден, как вы думаете!)
(Изменить). Мне не нужен праймер в том, что означает "сложность". Я хочу получить четкий ответ, возможно, с кавычками из стандарта С++, который точно скажет, что должно быть постоянный. Процессорные тики, реальное время или что-то еще? В других потоках некоторые люди утверждали, что время совершенно не имеет отношения к тому, что требуется стандарту С++.)
Соответствуют ли эти требования сложности в стандарте для времени выполнения операции? Или они просто указывают (максимальное) количество копий/ходов, которые могут произойти из содержащихся объектов? И что именно означает "амортизация"?
1.. При заданном (непустом) vector<int> v
, во время выполнения, очевидно, является постоянным:
swap(v.front(), v.back());
(хотя педант может указать, что это зависит от того, находятся ли данные в кеше или поменялись или что-то еще!).
2. Учитывая list<int> l
, сделать push_back
просто. Точно выделяется один новый элемент, и несколько указателей в связанном списке перетасовываются. Каждый push_front включает в себя одно распределение, всегда одного и того же объема памяти, поэтому это явно "постоянное". Но, конечно же, время для выделения может быть довольно переменным. Для управления памятью, возможно, потребуется много времени, чтобы найти подходящую свободную память.
3. Но сделать push_back
на a vector<int>
еще более непредсказуем. В большинстве случаев это будет очень быстро, но время от времени ему придется перераспределять пространство для всех данных и копировать каждый элемент в новое место. Таким образом, он менее предсказуем с точки зрения времени выполнения, чем один list::push_front
, но он по-прежнему называется постоянным (амортизируется). В среднем, добавление большого количества данных в вектор займет сложность, которая не зависит от добавленной суммы, и именно поэтому она называется "амортизированным постоянным" временем. (Правильно?)
И, наконец, я спросил о int
, чтобы избежать сложностей с другим типом. Например, a vector< vector<int> >
может быть немного сложнее рассуждать о том, что каждый элемент вектора (векторов) может иметь разный размер и, например, замена двух элементов не такая постоянная, как в случае 1. выше. Но в идеале мы могли бы ответить за все vector<T>
, а не только на T=int
.
(*) Для примера обсуждений см. комментарии к этим ответам: Какая структура данных, в точности, является deques в С++?