быстрый способ реализовать 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