整数0...N-1
から何らかのタイプのリストへのマッピングを頻繁に表す必要がありますT
。個々のリストには、要素を動的に最後に追加する必要があります。N
通常、事前にわかっています (ただし、コンパイル時ではありません)。個々のリストにすばやくアクセスする必要があります。
私は通常、 を使用してこれを実装しvector<vector<T> > my_map(N)
、 を使用my_map[key].push_back(val)
して要素を追加します。
2 つの質問があります。
これは、そのようなマップを実現するための効率的で推奨される方法ですか?
また、要素の連続性とサイズ変更への影響についても疑問に思います。たとえば、 で要素を追加しmy_map[key].push_back(val)
、 でサイズを変更する必要があるとmy_map[key]
しkey != N-1
ます。my_map
これは、内容を連続させておくために、ベクター全体のコピーをトリガーしますか? それともmy_map
、ヒープ上のベクトルへのポインタで内部的に実現されていますか?
これはSTLの実装に依存する可能性があることを認識しています。私は主に、Visual Studio 2010 と Linux の GCC のメカニズム (および速度への影響) に関心があります。
アップデート
コメントの中で、@PeterWoodstd::deque
はリストのコンテナとして私を指摘しました。asと比較するために非科学的なベンチマークをvector< deque<T> >
行いvector< vector<T> >
ました。どちらも、30 個の要素を持つ 100 万個のリストと、それぞれ 3000 個の要素を持つ 10,000 個のリストの時間を計りました。私のテストは、このタイプのデータ構造の典型的なアプリケーション シナリオを反映していることに注意してください。unsigned int
T
次のように機能するランダムアクセスの「ビルドアップ」の時間を計りました。
vector<ContainerT> my_map(numKeys);
vector<unsigned int> random_keys(numKeys);
for (unsigned int i=0; i<numKeys; ++i) random_keys[i] = i;
random_shuffle(random_keys.begin(),random_keys.end());
for (auto pKey=random_keys.begin(); pKey!=random_keys.end(); ++pKey)
{
for (unsigned int i=0; i<listSize; ++i)
{
my_map[*pKey].push_back( rand() );
}
}
そして、ランダムに選択されたリストから 3,000 万のランダムな要素をクエリするタイミングを計りました。
結果
deque
多くの小さなリストの構築はわずかに高速ですが、両方のシナリオのベクトルよりもクエリが遅くなります。vector< vector<T> >
私は自分のタイプの問題のために一緒にいると結論付けています。
deque
Keys: 1000000, list size: 30
Mean time buildup: 1.29517 seconds
Mean time query: 4.17624 seconds
Keys: 10000, list size: 3000
Mean time buildup: 0.998761 seconds
Mean time query: 5.052 seconds
vector
Keys: 1000000, list size: 30
Mean time buildup: 1.5347 seconds
Mean time query: 1.63043 seconds
Keys: 10000, list size: 3000
Mean time buildup: 0.604954 seconds
Mean time query: 1.58328 seconds