効果的なSTLで、
vectorは、デフォルトで使用されるシーケンスのタイプです。
それはどういう意味ですか?効率を無視vector
しても何でもできるようです。
誰かが私にvector
実現可能なオプションではないlist
が使用する必要があるシナリオを提供できますか?
効果的なSTLで、
vectorは、デフォルトで使用されるシーケンスのタイプです。
それはどういう意味ですか?効率を無視vector
しても何でもできるようです。
誰かが私にvector
実現可能なオプションではないlist
が使用する必要があるシナリオを提供できますか?
回答:
list
持っているpush_front
ベクター:
リスト:
一般に、使用しているシーケンシャルコンテナーの種類が気にならない場合はベクターを使用しますが、コンテナーの最後以外の場所への挿入や消去を多数行っている場合は、リストを使用する。または、ランダムアクセスが必要な場合は、リストではなくベクトルが必要になります。それ以外にも、アプリケーションに基づいてどちらかが必要になる場合もありますが、一般的には、これらが適切なガイドラインです。
reserve()
てO(1)に減らすことができます。リストに新しいアイテムを追加する(つまり、それらをスプライスしない)と、O(n)フリーストアの割り当てが実行されます。
list
要素を消去するときにメモリを解放しますが、解放vector
しないことです。トリックvector
を使用しない限り、サイズを小さくしてもAの容量は減少しませんswap()
。
ここでのほとんどの回答は、1つの重要な詳細を欠いています。
容器に何を入れておきたいですか?
それはの集まりである場合int
の、そしてstd::list
あなたは再割り当てすることができる場合に関係なく、あなただけなど、フロントから削除リストが遅くトラバースにあり、すべての挿入があなたのアロケータとの相互作用がかかり、すべてのシナリオに失うことになります。list<int>
ビートする例を準備するのは非常に難しいでしょうvector<int>
。そしてそれでも、deque<int>
リストの使用を正当化するのではなく、より良いか近いかもしれません。これはより大きなメモリのオーバーヘッドを持ちます。
ただし、大規模で見苦しいデータのブロブを処理している場合(およびそれらのいくつか)、挿入時に割り当てを行いたくない場合、再割り当てが原因でコピーが失敗することになります。その場合は、list<UglyBlob>
よりvector<UglyBlob>
。
それでも、vector<UglyBlob*>
またはに切り替えるとvector<shared_ptr<UglyBlob> >
、再び-リストは遅れます。
したがって、アクセスパターン、ターゲットエレメント数などは依然として比較に影響しますが、私の見解では、エレメントサイズ-コピーのコストなどです。
list<T>
の可能性です。一定時間のスプライシングが必要な場合は、listを選択することもできます;)splice
UglyBlob
-少数の文字列メンバーのみを含むオブジェクトでさえ、コピーするのは非常に高くつくため、再割り当てにはコストがかかります。またvector
、サイズが数十バイトの保持オブジェクトの指数関数的増加によって引き起こされる可能性のあるスペースオーバーヘッドを無視しないでください(reserve
事前にできない場合)。
vector<smart_ptr<Large>>
vsと同様list<Large>
-要素へのランダムアクセスが必要な場合、それvector
は理にかなっています。ランダムアクセスが必要ない場合、list
はより簡単に見え、同等に実行する必要があります。
std :: listの特別な機能の1つはスプライシングです(リストの一部または全体を別のリストにリンクまたは移動する)。
または、コンテンツのコピーに非常に費用がかかる場合。このような場合、たとえば、コレクションをリストでソートする方が安上がりです。
また、コレクションが小さい場合(および内容をコピーするのに特にコストがかからない場合)、どこかに挿入および消去しても、ベクターはリストよりも優れている場合があります。リストは各ノードを個別に割り当てますが、いくつかの単純なオブジェクトを移動するよりもはるかにコストがかかる可能性があります。
非常に難しいルールはないと思います。これは、コンテナの主な目的、およびコンテナの大きさや含まれる型に依存します。内容は単一の連続したブロックとして割り当てられるため、ベクトルは一般にリストよりも優先されます(基本的には動的に割り当てられる配列であり、ほとんどの状況で配列は一連のものを保持する最も効率的な方法です)。
list::size
必ずしも一定の時間ではありません。stackoverflow.com/questions/228908/is-listsize-really-onおよびgcc.gnu.org/ml/libstdc++/2005-11/msg00219.html
splice
線形複雑度として指定されている別のリストの間でsize
、具体的に一定です。そのため、反復する初心者に対応するためにsize
、アルゴリズムのクラス全体は、STL、または「準拠」コンテナ期間の対象外です。
私のクラスの生徒は、ベクターを使用する方が効果的である場合は説明できないようですが、リストを使用するようにアドバイスすると、とても幸せそうです。
これは私がそれを理解する方法です
リスト:各アイテムには次または前の要素へのアドレスが含まれているため、この機能を使用すると、アイテムがランダム化され、並べ替えられていなくても順序は変わりません。メモリが断片化されている場合は効率的です。ただし、これには他の非常に大きな利点もあります。項目を簡単に挿入/削除できるため、必要なのは一部のポインターを変更することだけです。欠点:ランダムな単一のアイテムを読み取るには、正しい住所が見つかるまでアイテム間をジャンプする必要があります。
ベクトル:ベクトルを使用する場合、メモリは通常の配列のようにはるかに編成されます。各n番目のアイテムは(n-1)番目のアイテムの直後と(n + 1)番目のアイテムの前に格納されます。リストよりも優れているのはなぜですか?ランダムアクセスが高速になるためです。方法は次のとおりです。ベクトル内のアイテムのサイズがわかっていて、それらがメモリ内で連続している場合、n番目のアイテムがどこにあるかを簡単に予測できます。必要なものを読むためにリストのすべての項目を参照する必要はありません。ベクトルを使用すると、直接読み取ることができますが、できないリストを使用できます。一方、ベクトル配列を変更したり、値を変更したりすると、はるかに時間がかかります。
メモリ内で追加/削除できるオブジェクトを追跡するには、リストがより適切です。大量の単一アイテムから要素にアクセスする場合は、ベクターがより適切です。
リストがどのように最適化されるのかはわかりませんが、高速な読み取りアクセスが必要な場合はベクターを使用する必要があることを知っておく必要があります。STLがリストを固定する速度は、ベクターよりも読み取りアクセスの速度が遅くなるためです。
vector
reserve()
基本的に、ベクトルは自動メモリ管理を備えた配列です。データはメモリ内で連続しています。途中でデータを挿入しようとすると、コストがかかります。
リストでは、データは無関係なメモリ位置に保存されます。真ん中に挿入することは、新しいデータのための場所を作るためにデータの一部をコピーすることを含みません。
より具体的にあなたの質問に答えるために、このページを引用します
ベクトルは通常、要素にアクセスし、シーケンスの最後に要素を追加または削除するのに最も効率的です。要素を末尾以外の位置に挿入または削除する操作の場合、デックやリストよりもパフォーマンスが低く、リストよりも反復子と参照の一貫性が低くなります。
シーケンスの途中で多くの挿入または削除がある場合。例えば、メモリマネージャ。
イテレータの有効性を維持することは、リストを使用する1つの理由です。もう1つは、アイテムをプッシュするときにベクトルを再割り当てしたくない場合です。これは、reserve()のインテリジェントな使用によって管理できますが、場合によっては、リストを使用する方が簡単または実現可能です。
コンテナ間でオブジェクトを移動する場合は、を使用できますlist::splice
。
たとえば、グラフ分割アルゴリズムは、一定数のオブジェクトを、増加する数のコンテナ間で再帰的に分割できます。オブジェクトは一度初期化する必要があり、常にメモリ内の同じ場所に残ります。再割り当てを行うよりも、再リンクを行う方がはるかに高速です。
編集:ライブラリーがC ++ 0xを実装する準備をするにつれて、サブシーケンスをリストにスプライスする一般的なケースは、シーケンスの長さに比例して複雑になります。これは、splice
(今)シーケンス内の要素の数をカウントするためにシーケンスを反復する必要があるためです。(リストはそのサイズを記録する必要があるためです。)リストを数え、再リンクするだけでも、他のどの方法よりも速く、リスト全体または単一の要素を接合することは、一定の複雑さを持つ特殊なケースです。ただし、スプライスする長いシーケンスがある場合は、古くて古くて非準拠のより良いコンテナーを探し回る必要があるかもしれません。
list
使用する必要がある唯一の難しいルールは、コンテナーの要素へのポインターを配布する必要がある場合です。
とは異なりvector
、要素のメモリは再割り当てされません。それが可能であれば、未使用のメモリへのポインタがある可能性があります。これは、せいぜい大きなno-noで、最悪の場合はa SEGFAULT
です。
(技術的には、vector
の*_ptr
も、希望の仕事が、その場合には、あなたがエミュレートされているlist
ことはただ意味をですので。)
他のソフトルールは、コンテナーの中央に要素を挿入することで起こり得るパフォーマンスの問題に関係しているため、list
推奨されます。
シンプルに
する-結局のところ、C ++でのコンテナーの選択が混乱しているときは、このフローチャートの画像を使用してください(私に感謝します):-
ここに画像の説明を入力してください
ベクター-
1.ベクトルは伝染性メモリに基づいています
。2.ベクトルが小さなデータセットのために行くための方法です
。3.ベクトルをデータ・セットに横断しながら、最速の実行
4.ベクター挿入の削除は、巨大なデータセットに遅いですが、高速で非常に小さいため
リスト-1 .リストはヒープメモリに基づいています
2.リストは非常に巨大なデータセットを処理する方法です
3.リストは小さなデータセットのトラバースでは比較的低速ですが、巨大なデータセットで
は高速です4.リストの挿入削除は高速です巨大なデータセットですが、小さいデータセットでは遅くなります
ベクトルとリストの場合、私に突き出る主な違いは次のとおりです。
ベクター
ベクトルはその要素を連続したメモリに格納します。したがって、ベクター内でランダムアクセスが可能です。これは、ベクターの要素にアクセスするためにベースアドレスとアイテムインデックスを単純に乗算できるため、ベクターの要素へのアクセスが非常に高速であることを意味します。実際、この目的にはO(1)または一定の時間しかかかりません。
ベクトルは基本的に配列をラップするため、要素をベクトル(動的配列)に挿入するたびに、メモリの新しい隣接ブロックを見つけてサイズを変更し、時間のかかる新しい要素に対応する必要があります。
その中に他の要素へのポインタを格納するために余分なメモリを消費しません。
リスト
リストはその要素を非連続メモリに格納します。したがって、リスト内でのランダムアクセスは不可能です。つまり、その要素にアクセスするには、ポインターを使用して、ベクターに比べて遅いリストを走査する必要があります。これにはO(n)またはO(1)より遅い線形時間がかかります。
リストは不連続なメモリを使用するため、リスト内に要素を挿入するのにかかる時間は、メモリの再割り当てが回避されるため、対応するベクトルの場合よりもはるかに効率的です。
特定の要素の前後の要素へのポインタを格納するために、余分なメモリを消費します。
したがって、これらの違いを念頭に置いて、通常はメモリ、頻繁なランダムアクセス、挿入を考慮して、特定のシナリオでベクトルとリストの勝者を決定します。