web-dev-qa-db-ja.com

pop_frontをstd :: vectorに実装する高速な方法

Std :: vectorを使用するいくつかのクラスといくつかのユーティリティメソッドを使用しています。

次に、これらのクラスの1つで各フレームにpop_front-Push_backメソッドを使用する必要があります(ただし、それらはすべてリンクされており、1つだけを変更できないように連携します)。

ほとんどの操作は、すべての要素操作とPush_back操作に対して繰り返されるため、最良の作業を行うためには、これらのクラスとユーティリティのリポジトリをフォークし、すべてをテンプレート化し、dequeまたはlistを使用します。

しかし、これは多くのコードの書き直しと多くのテストを意味し、締め切りを逃します。

したがって、効率的な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());
}

これら2つのソリューションの高速化とは何ですか?他のソリューションはありますか?

20
nkint

私は期待するだろう:

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操作は定義によりコンテナから要素を削除します。

29
Mankarse

pop_front()は最初の要素のみを消去するため、直接の実装は次のとおりです。

template <typename V>
void pop_front(V & v)
{
    assert(!v.empty());
    v.erase(v.begin());
}

今のところ速度について心配しないでください。戻ってコードを最適化する場合は、専用のプロジェクト時間を要求してください。

6
Kerrek SB

最初の要素を消去しようとする場合は、関数で次を使用します。

if (my_vector.size()){ //check if there any elements in the vector array
    my_vector.erase(my_vector.begin()); //erase the firs element
}

ベクトル配列全体のポップフロントをエミュレートしたい場合(最初から最後まですべての要素をポップアウトしたい)、私は提案します:

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
1
0xPwn

私にも方法があります...あまり良くありません。

これは@ 0xPwnの解決策のように見えますが、2度目はベクトルを反転しませんでした。あなたはおそらくこのコードを理解するので、説明しません。

#include <algorithm>
#include <vector>
template <typename T>
void pop_front(std::vector<T>& vec){
    std::reverse(vec.begin(),vec.end()); // first becomes last, reverses the vector
    vec.pop_back(); // pop last
    std::reverse(vec.begin(),vec.end()); // reverses it again, so the elements are in the same order as before

}
1
CppPythonDude