быстрый способ реализовать Pop front в std::vector
Я использую некоторые классы и несколько методов утилиты, которые используют std::vector.
теперь мне нужно использовать каждый кадр pop_front - push_back метод на одном из этих классов (но все они связаны и работают вместе, поэтому я не могу изменить только один).
большинство операций повторяются над всеми операциями element и push_back, поэтому для лучшей работы я должен сделать следующее: разветвить репозиторий этих классов и утилит, создать шаблон и использовать deque или список.
но это означает много перезаписи кода и много тестирования, которые заставят меня пропустить крайний срок.
поэтому мне нужен совет, чтобы написать эффективный pop_front для вектора статического размера (размер не изменится).
Я нашел здесь образом:
template<typename T>
void pop_front(std::vector<T>& vec)
{
vec.front() = vec.back();
vec.pop_back();
vec.front() = vec.back(); // but should this work?
}
и еще одна мысль должна быть:
template<typename T>
void pop_front(std::vector<T>& vec, already_allocated_vector vec1)
{
vec1.clear();
copy(vec.begin(), vec.end()-1, vec1.begin());
copy(vec1.begin(), vec1.end(), vec.begin());
}
что быстрее из этих двух решений? Есть другие решения?
4 ответов
Я бы ожидал:
template<typename T>
void pop_front(std::vector<T>& vec)
{
assert(!vec.empty());
vec.front() = std::move(vec.back());
vec.pop_back();
}
наиболее эффективным способом сделать это, но он не сохраняет порядок элементов в векторе.
Если вам нужно поддерживать порядок остальных элементов vec
, вы можете сделать:
template<typename T>
void pop_front(std::vector<T>& vec)
{
assert(!vec.empty());
vec.erase(vec.begin());
}
это будет иметь линейное время в число элементов vec
, но это лучшее, что вы можете сделать, не изменяя структуру данных.
ни одна из этих функций будет поддерживать vector
при постоянном размере, поскольку pop_front
операция по определению удалить элемент из контейнера.
С pop_front()
стирает только первый элемент, прямые реализации-это:
template <typename V>
void pop_front(V & v)
{
assert(!v.empty());
v.erase(v.begin());
}
пока не беспокойтесь о скорости. Если вы хотите вернуться и оптимизировать код, попросите выделенное время проекта.
вы также можете IgushArray (https://github.com/igushev/IgushArray) который как массив имеет быструю деятельность доступа постоянн-времени, но деятельность вставки/стирания принимает только время о (н^1/2). Таким образом, в вашем случае вставка в начале будет очень эффективным. Будьте осторожны, структура очень чувствительна для резерва().
template <class T>
void pop_front(IgushArray<T>& v)
{
if (!v.empty())
v.erase(v.begin());
}
в первом варианте вы написали, что нарушаете порядок элементов. Это проблема?
если да, используйте вариант I писал.
если нет и порядок элементов не имеет значения, может быть, лучше использовать std::set или std:: multiset.
Если вы просто попытаетесь стереть первый элемент, то в функции используйте:
if (my_vector.size()){ //check if there any elements in the vector array
my_vector.erase(my_vector.begin()); //erase the firs element
}
Если вы хотите эмулировать Pop front для всего векторного массива ( вы хотите, чтобы каждый элемент выскакивал от начала до конца), я предлагаю:
reverse(my_vector.begin(),my_vector.end()); // reverse the order of the vector array
my_vector.pop_back(); // now just simple pop_back will give you the results