web-dev-qa-db-ja.com

C ++ STLリストとセット

ランダムな挿入と削除の場合、これら2つのうちどちらが高速ですか?リストのように、セットの場合と同じように値をキーとして持つことも魅力的なようです。コンテナ全体を反復する場合のパフォーマンスは同じですか?

ありがとう!

22
user240137

リスト

  1. 検索(線形時間)。
  2. 挿入、削除、移動(一定の時間がかかります)。
  3. 要素は注文できます。
  4. 要素はソートできます。
  5. 要素が重複している可能性があります。

設定

  1. 検索(サイズが対数)。
  2. 挿入と削除(一般的に対数)。
  3. 要素は順序付けられていません。
  4. 要素は常に低いものから高いものへと並べ替えられます。
  5. 要素はユニークです。
36
cpx

std :: list is O(1)挿入および削除の場合。ただし、挿入または削除ポイントを見つけるにはO(n)が必要になる場合があります。std :: set is O(log(n))挿入と削除の場合、通常は赤黒木として実装されます。

挿入/削除ポイントを見つけて選択する努力を検討してください。

19
Hans Passant

最初にセマンティクスについて考え、次にパフォーマンスについて考えます。

整数のセットがあり、それに整数6、8、13、8、20、6、および50を挿入すると、次の5つの要素を含むセットになります。{ 6, 8, 13, 20, 50 }.

リストを使用してこれを行うと、次の7つの要素を含むリストになります。{ 6, 8, 13, 8, 20, 6, 50 }

それであなたは何をしたいのですか?コンテナの速度をそのような異なるセマンティクスと比較することは意味がありません。

11
Daniel Daranas

Std :: listでは、挿入と削除自体にO(1)で時間がかかります。つまり、非常に高速であり、とりわけ、の要素数に依存しない速度であるということです。リスト。

Std :: setでは、O(log(N))での挿入と削除に時間がかかります。つまり、セットに多くの要素が含まれていると少し遅くなります。式O(log(N))のNは、要素の数を意味します。 Grosso modoは、演算にかかる時間が要素数の対数に比例することを意味します(理論的なアルゴリズム分析では無視される定数を掛けることに相当するため、ここでは底は重要ではありません)。セットで。

ただし、削除する要素を見つけるのにかかる時間を考慮することが重要です。削除する要素をコンテナで検索する必要がある場合(ほとんどの場合)、std :: listはこの検索に非常に長い時間がかかり、O(N)(つまり、高速ではない、時間は要素の数に正比例し、その対数ではないため)、std :: setは検索のためにO(log N)で時間がかかります。

また、これらの理論的分析は、要素が非常に少ないコンテナでは完全に無効になることに注意してください。その場合、それらが非表示にする乗算定数は、焦点を当てる時間関数ファミリよりも重要になります。

短くするには:std :: list =>削除する要素の検索が遅くなります。削除するのが速くなります。 std :: set =>削除する要素の検索が高速化。削除する速度が遅くなります。

ただし、操作全体および多数の要素の場合は、std :: setの方が優れています。

ハッシュテーブルの使用も検討する必要があります。それらの優れた実装は、Boost、Qt、またはC++ 0xで利用できます。それらは、O(1)(つまり、非常に高速)に向かう傾向がある時間内にこれらすべての操作を実行します。

3
Dom

速度が気になる場合は、おそらくstd::vectorを使用する必要があります。 std::listは、要素が挿入されるたびに1つのヒープ割り当てを実行します。これは、通常、ボトルネックです。

例外は、個々のアイテムのコピーに非常に費用がかかる場合、またはアイテムが非常に多い場合です。このような場合、リストのサイズが変更されたときにアイテムを移動する必要がないため、リストのパフォーマンスが向上する可能性があります。ここではstd::dequeも適切なオプションですが、2つを決定するには、アプリケーションのプロファイルを作成する必要があります。

最後に、std::setは、アイテムを並べ替えておく必要がある場合(または、アイテムを繰り返したくない場合)にのみ使用してください。そうしないと、リストやベクターよりも大幅に遅くなります。

2
Manuel

現実的なデータで現実的な使用法を使用して、パフォーマンスを自分で測定する必要があります。典型的なパフォーマンスと最悪の場合のパフォーマンスの両方を確認してください。

Std :: vectorにはランダム挿入の時間計算量がO(N)ですが、std :: set O(log(N))およびstd :: list O(1)、std :: vectorは多くの場合最高のパフォーマンスを発揮します。パフォーマンスが測定に時間を費やすほど重要でない場合にのみ、big-Oの複雑さを乗り越えてください。

"測定していない場合はエンジニアリングしていない"(Rico Mariani)

2
Don Reba