STLにソートされたコンテナはありますか?
つまり、std::vector<Foo>
があります。Foo
はカスタムメイドのクラスです。クラスFoo
のフィールドを比較する何らかのコンパレーターもあります。
今、私のコードのどこかでやっています:
std::sort( myvec.begin(), myvec.end(), comparator );
コンパレータで定義したルールに従ってベクトルをソートします。
次に、クラスFoo
の要素をそのベクターに挿入します。できれば、ただ書きたいと思います。
mysortedvector.Push_back( Foo() );
そして何が起こるかというと、ベクターはコンパレーターに従ってこの新しい要素をその場所に配置します。
代わりに、今私は書く必要があります:
myvec.Push_back( Foo() );
std::sort( myvec.begin(), myvec.end(), comparator );
ベクトルは既にソートされており、必要なのは新しい要素を適切に配置するだけなので、これは時間の無駄です。
私のプログラムの性質上、キーと値のペアがなく、単純なベクターだけなので、std::map<>
は使用できません。
stl::list
を使用する場合、挿入するたびにsortを再度呼び出す必要があります。
はい、 - std::set
、 std::multiset
、 std::map
、および std::multimap
はすべて std::less
はデフォルトの比較操作として。使用される基本的なデータ構造は、通常、赤黒木などのバランスの取れた二分探索木です。したがって、これらのデータ構造に要素を追加してから、含まれている要素を反復処理すると、出力はソートされた順序になります。データ構造にN個の要素を追加する複雑さはO(N log N)、または一般的なO(log N)複雑さの並べ替えを使用してN要素のベクトルを並べ替えることと同じです。
特定のシナリオでは、キー/値のペアがないため、std::set
またはstd::multiset
がおそらく最善の策です。
Jasonの answer を拡張したいと思います。 _std::set
_ または _std::multiset
_ のいずれかが特定のシナリオに最適な選択肢であることに、Jasonに同意します。選択肢をさらに絞り込むための例を提供したいと思います。
次のクラスFoo
があると仮定します。
_class Foo {
public:
Foo(int v1, int v2) : val1(v1), val2(v2) {};
bool operator<(const Foo &foo) const { return val2 < foo.val2; }
int val1;
int val2;
};
_
ここで、Foo
は_<
_演算子をオーバーロードします。このように、明示的なコンパレータ関数を指定する必要はありません。その結果、次の方法で_std::multiset
_の代わりに_std::vector
_を使用できます。 Push_back()
をinsert()
に置き換えるだけです:
_int main()
{
std::multiset<Foo> ms;
ms.insert(Foo(1, 6));
ms.insert(Foo(2, 5));
ms.insert(Foo(3, 4));
ms.insert(Foo(1, 4));
for (auto const &foo : ms)
std::cout << foo.val1 << " " << foo.val2 << std::endl;
return 0;
}
_
出力:
3 4
2 4
1 5
1 6
ご覧のとおり、コンテナは_val2
_演算子に基づいて、クラスFoo
のメンバー_<
_でソートされます。ただし、_std::set
_の代わりに_std::multiset
_を使用すると、異なる出力が得られます。
_int main()
{
std::set<Foo> s;
s.insert(Foo(1, 6));
s.insert(Foo(1, 5));
s.insert(Foo(3, 4));
s.insert(Foo(2, 4));
for (auto const &foo : s)
std::cout << foo.val1 << " " << foo.val2 << std::endl;
return 0;
}
_
出力:
3 4
1 5
1 6
ここでは、_val2
_が4である2番目のFoo
オブジェクトが欠落しています。これは、_std::set
_が一意のエントリのみを許可するためです。エントリが一意かどうかは、提供された_<
_演算子に基づいて決定されます。この例では、_<
_演算子は_val2
_メンバーを相互に比較します。したがって、2つのFoo
オブジェクトは、それらの_val2
_メンバーが同じ値を持つ場合、等しくなります。
したがって、選択は_<
_演算子に基づいて等しい可能性のあるFoo
オブジェクトを保存するかどうかによって異なります。