Я хотел бы удалить элементы из вектора в обратном порядке, начиная с последнего элемента. Насколько я знаю, самый простой способ сделать это с помощью итератора:
std::vector<int> data = ...
std::vector<int>::iterator iter;
for(iter = data.end() - 1; iter != data.begin() - 1; iter--) {
data.erase(iter);
}
Мой вопрос заключается в том, будет ли каждый из этих вызовов erase () быть O (1), так как мы удаляем в конце, даже если общая сложность удаления — O (n)? Кроме того, является ли этот код «безопасным», предполагая, что вектор имеет хотя бы 1 элемент?
Нет, ваш алгоритм имеет UB.
Если бы не было, у него было бы O (n).
Изменение тела на это приведет к удалению UB: iter = data.erase(iter);
Зачем? Так как vector.erase()
ведет себя так:
Если переписать цикл следующим образом, он будет работать даже для пустого контейнера:
for(auto it = data.end(); it!=data.begin(); it = data.erase(it-1)) /**/;
Это равно:
std::remove_if(data.rbegin(), data.rend(), [](data::reference x){return true;});
Во всяком случае, используя data.clear()
, data.resize(0)
или обмен с временным пустым вектором, скорее всего, будет быстрее.
Если вы действительно необходимость чтобы удалить их в обратном порядке, вам лучше просто позвонить data.clear()
,
В противном случае нет, это не «безопасно»: формирование data.begin() - 1
не определено, и уменьшается iter
после того как ты позвонил .erase
на это тоже не определено. Deduplicator опубликовал хорошее исправление для этого.
Своего рода. Сложность std :: vector erase () равна
Линейный по количеству стертых элементов (разрушений) плюс количество элементов после последнего удаленного элемента (перемещение).
На основании этого источника: http://www.cplusplus.com/reference/vector/vector/erase/
Поскольку вы удаляете только один элемент и его последний элемент, он является линейным с N = 1, что можно интерпретировать как O (1) константу.