web-dev-qa-db-ja.com

insert()などをサポートするsort_vectorクラスはありますか?

多くの場合、std::vectorの代わりにソートされたstd::setを使用する方が効率的です。ライブラリクラスsorted_vectorを知っている人はいますが、これは基本的にstd::setと同様のインターフェイスを持ちますが、並べ替えられたベクトルに要素を挿入し(重複がないように)、バイナリ検索を使用してfind要素など?

書くのは難しくありませんが、時間を無駄にせずに既存の実装を使用する方が良いでしょう。

更新:セットの代わりにソートされたベクトルを使用する理由は次のとおりです。それぞれ10個程度のメンバーのみを含む数十万個の小さなセットがある場合、ソートを使用する方がメモリ効率が高い代わりにベクトル。

53
Frank

Boost.Container flat_set

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は最後-最初。

28
Evgeny Panasyuk

このようなコンテナが標準ライブラリの一部ではない理由は、非効率的だからです。ストレージにベクターを使用すると、ベクターの中央に何かが挿入された場合、オブジェクトを移動する必要があります。 every挿入でこれを行うと、不必要に高価になります。 (平均すると、挿入ごとにオブジェクトの半分を移動する必要があります。それはかなりコストがかかります)

ソートされたベクトルが必要な場合は、すべての要素を挿入し、挿入後にstd::sort()onceを呼び出した方がよいでしょう。

7
jalf

ほとんどすべての場合に使用するのに適したものをソートするための適切な連想コンテナがすでに存在するため、STLには「ソートされたコンテナ」アダプタがないと思います。正直に言うと、ソートされたvector<>コンテナは、ソートされた配列を期待するC関数と相互運用する場合があります。もちろん、何かが足りないかもしれません。

ソートされたvector<>は、(ベクターに要素を挿入することの欠点を認識している)あなたのニーズにより適しているでしょう。ここにコードプロジェクトの実装があります:

私は一度も使用したことがないので、それを保証することはできません(または、ライセンスが指定されている場合)。しかし、この記事を簡単に読んだところ、少なくとも著者が適切なSTLインターフェイスを持つようにコンテナーアダプターに多大な努力を払ったようです。

よく見る価値があるようです。

5
Michael Burr

自分でロールバックすることに決めた場合は、boost:ublasもチェックしてください。具体的には:

#include <boost/numeric/ublas/vector_sparse.hpp>

そして、値とインデックスのベクトルを実装するordinate_vectorを見てください。このデータ構造はO(1)挿入(並べ替えに違反))をサポートしますが、オンデマンドでOmega(n log n)を並べ替えます。もちろん、並べ替えると、検索はO(logn)配列の一部がソートされている場合、アルゴリズムはこれを認識し、新しく追加された要素のみをソートしてからインプレースマージを実行します。

4
Neil G

AlexandresuのLokiには、あなたが所有するロールの相対的な取るに足りない努力をしたくない場合、ソートされたベクトル実装があります。

http://loki-lib.sourceforge.net/html/a00025.html

3
Lance Diduck

ここ は、私が長年にわたって実動コードで使用してきたsort_vectorクラスです。カスタムの述語を使用できるようにするオーバーロードがあります。ポインターのコンテナーに使用しましたが、これは多くのユースケースで本当に素晴らしいソリューションになります。

0
moodboom