多くの場合、std::vector
の代わりにソートされたstd::set
を使用する方が効率的です。ライブラリクラスsorted_vector
を知っている人はいますが、これは基本的にstd::set
と同様のインターフェイスを持ちますが、並べ替えられたベクトルに要素を挿入し(重複がないように)、バイナリ検索を使用してfind
要素など?
書くのは難しくありませんが、時間を無駄にせずに既存の実装を使用する方が良いでしょう。
更新:セットの代わりにソートされたベクトルを使用する理由は次のとおりです。それぞれ10個程度のメンバーのみを含む数十万個の小さなセットがある場合、ソートを使用する方がメモリ効率が高い代わりにベクトル。
Boost.Container flat_ [multi] map/setコンテナは、AusternおよびAlexandrescuのガイドラインに基づく順序付きベクトルベースの連想コンテナです。これらの順序付けされたベクトルコンテナは、最近C++に移動セマンティクスが追加され、挿入と消去の時間が大幅に短縮されたため、メリットがあります。フラット連想コンテナには次の属性があります。
- 標準の連想コンテナよりも高速な検索
- 標準の連想コンテナよりもはるかに高速な反復。
- 小さなオブジェクト(およびshrink_to_fitが使用されている場合は大きなオブジェクト)のメモリ消費が少ない
- キャッシュパフォーマンスの向上(データは連続したメモリに保存されます)
- 非安定イテレーター(要素の挿入および消去時にイテレーターが無効化されます)
- コピー不可および移動不可の値タイプは保存できません
- 標準の連想コンテナよりも弱い例外安全性(消去/挿入で値をシフトするときに、コピー/移動コンストラクターがスローできる)
- 標準の連想コンテナよりも挿入と消去が遅い(特に移動できないタイプの場合)
ライブデモ :
#include <boost/container/flat_set.hpp>
#include <iostream>
#include <ostream>
using namespace std;
int main()
{
boost::container::flat_set<int> s;
s.insert(1);
s.insert(2);
s.insert(3);
cout << (s.find(1)!=s.end()) << endl;
cout << (s.find(4)!=s.end()) << endl;
}
jalf:ソートされたベクトルが必要な場合は、すべての要素を挿入し、挿入後にstd :: sort()を1回呼び出すことをお勧めします。
boost :: flat_set はそれを行うことができます自動的に:
template<typename InputIterator>
flat_set(InputIterator first, InputIterator last,
const Compare & comp = Compare(),
const allocator_type & a = allocator_type());
Effects:指定された比較オブジェクトとアロケータを使用して空のセットを構築し、範囲[first、last)から要素を挿入します。
Complexity:範囲[first、last)がすでにcompを使用してソートされている場合はNの線形、それ以外の場合はN * log (N)、Nは最後-最初。
このようなコンテナが標準ライブラリの一部ではない理由は、非効率的だからです。ストレージにベクターを使用すると、ベクターの中央に何かが挿入された場合、オブジェクトを移動する必要があります。 every挿入でこれを行うと、不必要に高価になります。 (平均すると、挿入ごとにオブジェクトの半分を移動する必要があります。それはかなりコストがかかります)
ソートされたベクトルが必要な場合は、すべての要素を挿入し、挿入後にstd::sort()
onceを呼び出した方がよいでしょう。
ほとんどすべての場合に使用するのに適したものをソートするための適切な連想コンテナがすでに存在するため、STLには「ソートされたコンテナ」アダプタがないと思います。正直に言うと、ソートされたvector<>
コンテナは、ソートされた配列を期待するC関数と相互運用する場合があります。もちろん、何かが足りないかもしれません。
ソートされたvector<>
は、(ベクターに要素を挿入することの欠点を認識している)あなたのニーズにより適しているでしょう。ここにコードプロジェクトの実装があります:
私は一度も使用したことがないので、それを保証することはできません(または、ライセンスが指定されている場合)。しかし、この記事を簡単に読んだところ、少なくとも著者が適切なSTLインターフェイスを持つようにコンテナーアダプターに多大な努力を払ったようです。
よく見る価値があるようです。
自分でロールバックすることに決めた場合は、boost:ublasもチェックしてください。具体的には:
#include <boost/numeric/ublas/vector_sparse.hpp>
そして、値とインデックスのベクトルを実装するordinate_vectorを見てください。このデータ構造はO(1)挿入(並べ替えに違反))をサポートしますが、オンデマンドでOmega(n log n)を並べ替えます。もちろん、並べ替えると、検索はO(logn)配列の一部がソートされている場合、アルゴリズムはこれを認識し、新しく追加された要素のみをソートしてからインプレースマージを実行します。
AlexandresuのLokiには、あなたが所有するロールの相対的な取るに足りない努力をしたくない場合、ソートされたベクトル実装があります。
ここ は、私が長年にわたって実動コードで使用してきたsort_vectorクラスです。カスタムの述語を使用できるようにするオーバーロードがあります。ポインターのコンテナーに使用しましたが、これは多くのユースケースで本当に素晴らしいソリューションになります。