2011-12-31 49 views
51

私は今STLを学んでいます。私はsetコンテナについて読む。 setを使用するときに質問がありますか? description of setを読んだ後は、vectorで置き換えることができるので、役に立たないようです。 vector vs setのプロとコスを言うことができますか?ありがとうstd :: setとstd :: vectorの違いは何ですか?

+1

あなたはセットについて読むこともできますので、地図もお読みください。それからもう一度比較しよう! –

+0

[注意して容器を選んでください](https://docs.google.com/open?id=0B_ZAqgwpqtF4MjQ5NmNlM2ItNTQxNS00MmEyLWFiODctNDk4YTY5MDRlYzQz) –

+0

@NicolBolasリンクを編集しました。あなたは私にいくつか余分な仕事をさせました:D –

答えて

71

setが発注されます。あなたが提供するファンクタによれば、が保証されたが特定の順序で残ることが保証されています。追加または削除する要素(setでは許可されていない複製を追加しない限り)は、常に注文されます。

vectorは、正確にはのみです。明示的に指定した順序です。 vectorのアイテムは、それらを置く場所です。あなたがそれらを順不同に置くと、それらは順不同です。今すぐsortする必要があります。確かに、setは、比較的限られた用途しか有さない。適切な訓練をすれば、vectorにアイテムを挿入して注文することができます。ただし、コンテナからアイテムを絶えず挿入したり取り出したりする場合は、vectorに多くの問題が発生します。それは実質的に単なる配列なので、要素のコピー/移動などをたくさんするでしょう。

vectorにアイテムを挿入するのにかかる時間は、既にvectorにあるアイテムの数に比例します。アイテムをsetに挿入するのにかかる時間は、項目数のlog2に比例します。アイテムの数が多い場合、それは大きな違いです。 log2(100,000)は〜16です。それは大きなスピードの向上です。削除の場合も同じです。

ただし、すべての挿入を一度に行うと、初期化時に問題はありません。 vectorにすべてを挿入して(その価格を一度支払って)並べ替えてから、ソートされたvectorsの標準アルゴリズムを使用して、要素を見つけてソートされたリストを反復処理することができます。 setの要素の反復はまったく遅くはありませんが、vectorを反復する方が高速です。

したがって、ソートされたvectorsetに勝つ場合があります。それが必要であることがわかっていない限り、この種の最適化の費用を気にする必要はありません。あなたが書いているシステムの種類に精通していない(したがってパフォーマンスが必要であることがわかっている)人がいなければsetを使用するか、setではなくvectorが必要であることを示すプロファイルデータを手元に持っていなければなりません。

+5

しかし、 'set'は実装の詳細だけではありませんか?数学的に言えば、集合には順序がありません。 –

+29

@PaulManta: 'std :: set'は数学では定義されていません。これはC++仕様で定義されています。仕様書には注文されていると記載されています。 –

+0

@ NicolBolas:なぜ "アイテムをベクトルに挿入するのにかかる時間は、すでにベクトルに入っているアイテムの数に比例しますか?" ? - あなたは常にinsert()を使用し、最後に挿入しないことを意味しますか? push_back()を使用してO(1)に追加できませんか?特にユーザが注文を制御しているためです。 –

7

ベクトルはどのように順序付けられているかを決めるだけでなく、好きなだけ多くの等しいものをベクトルに配置することもできます。セットはそのセットの内部ルール(ルールを設定することができますが、セットはそのオーダーを処理します)に従って並べられ、複数の等しいアイテムをセットに入れることはできません。

もちろん、ユニークなアイテムのベクトルを維持することはできますが、セット指向の操作を実行するとパフォーマンスが低下します。たとえば、10000個のアイテムのセットと、10000個の異なる順序付けられていないアイテムのベクトルがあるとします。ここで、値Xがセット内の値(またはベクトル内の値)の中にあるかどうかを確認する必要があるとします。 Xが項目の中にないとき、ベクトルの検索は約100倍遅くなります。集合体や交点の計算では、同様のパフォーマンスの違いがあります。要約すると、集合およびベクトルは異なる目的を有する。あなたはセットの代わりにベクトルを使うことができますが、それはもっと多くの作業を必要とし、パフォーマンスをかなり悪くする可能性があります。

+1

+1。私はこれを指摘するのに誰も気にしていないと信じられない。恥のために!一意性が主な利点です。それを評価することはできません。しかし、それを評価するのは簡単ではありません。しかし、スピードがないセットアップ部分でも、理論的には遅くても、 '' unordered_set ''を使用するように、 ''消去 '/ '懸念して、私はあまりにも後でコードを読むことができて心配です!例えば私はアイテムがコンテナに置かれていることを確認したいが、一度だけ行う。 'vec.find(it)!= vec.end()){vec.emplace(it)}'よりも 'set.emplace(it)'を書く方がはるかにいいようです。 ) –

5

ベクトル(O(log(n))対O(n))よりアイテムを検索する方が高速です。アイテムをベクトルに対して検索するには、ベクトル内のすべてのアイテムを繰り返し処理する必要がありますが、セットでは赤黒のツリーを使用して検索を最適化します。

このセットは順序付けされているため、最小のものから最大のものから順番に、または逆の順序でのみ反復できます。

しかし、ベクトルの順序は、挿入順序で移動することができます。

+1

本当ではありません。対数の比較を行う 'std :: vector'に対して' std :: binary_search'を実行することができます。 – Arlen

+25

しかし、バイナリ検索は、ベクトルがソートされている場合にのみ有効です。 – rsaxvc

2

フォームcpluplus.com セット:

セットは、特定の ため、以下のユニークな要素を格納するコンテナです。

に設定を注文した項目さVECTながら一意

に表される:

ベクターは サイズに変更することができる配列を表す配列のコンテナです。

ので、ベクトルは、あなたがそれを埋めるためにされ、複数の同一の項目

を保持することができます設定を好む:

  • あなたが解析したい場合は、複数の同一の値
  • をフィルタリングしたい場合指定された順序で項目を指定します(ベクトルでこれを行うには、特にベクトルをソートする必要があります)。

はベクトルを好む:

  • あなたは
  • 同一の値を保持したい場合は、あなたがそれらを押すのと同じ順序で項目を解析したい場合(あなたは、ベクトル注文を処理していないと仮定した場合)
関連する問題