std :: mapを反復する順序はわかっていますか(標準で保証されていますか)?


158

つまり、std::mapの要素はキーに従ってソートされています。したがって、キーが整数であるとしましょう。からstd::map::begin()std::map::end()使用して反復する場合for、標準では、昇順でソートされたキーを持つ要素を結果として反復することを保証していますか?


例:

std::map<int, int> map_;
map_[1] = 2;
map_[2] = 3;
map_[3] = 4;
for( std::map<int, int>::iterator iter = map_.begin();
     iter != map_.end();
     ++iter )
{
    std::cout << iter->second;
}

これは印刷が保証されています234か、それとも実装が定義されていますか?


現実の理由:私が持っているstd::mapintキー。非常にまれな状況で、具体的なint値よりも大きいキーを使用して、すべての要素を反復処理します。うん、それstd::vectorはより良い選択のように思えますが、私の「非常にまれな状況」に注意してください。


編集:私は知っている、の要素std::mapがソートされていることを知っています...それを指摘する必要はありません(ここでのほとんどの答えに対して)。私の質問にもそれを書きました。
コンテナーを反復処理するときに、イテレーターと順序について尋ねていました。答えてくれて@Kerrek SBに感謝します。


6
知らなかった場合:実際の使用map::upper_boundでは、反復を開始するポイントを見つけるために使用できます。
Steve Jessop、2011年

私はこれを知っており、反復を開始する正確な場所を知っています。注文が保証されるなら、私はたださまよった。
キリルキーロフ

疎なベクトルは、キー(数値インデックス)が全体で非常に大きく変化する場合には意味がありません。私は、数値インデックスが3次元空間のデカルトy座標を表す同様のソリューションを使用しています。このシナリオでベクトルを使用すると、メモリフットプリントがギガバイト増加します。そのため、ベクターは万能薬ではないと思います。
ジョナサンノイフェルト2014年

私はその質問を理解していません。その理由を思考実験で説明します。要素が順序付けられていることをすでに知っている場合、反復はどのようにできないのでしょうか?順序付けが反復に適用されない場合、それはどういう意味ですか?順序が重要である、検出可能であるなど、他にどのような場合がありますか?(答えはコンスタンチンによって与えられました。)
underscore_d

回答:


176

はい、保証されています。さらに、比較演算子によって決定される*begin()最小*rbegin()要素と最大要素、および2つのキー値ab提供し、式!compare(a,b) && !compare(b,a)が真であるは等しいと見なされます。デフォルトの比較関数はstd::less<K>です。

順序はラッキーボーナス機能ではありませんが、順序が2つのキーが同じ場合(上記のルールによって)を決定し、効率的なルックアップ(本質的にはバイナリ)を実行するために使用されるため、データ構造の基本的な側面です要素数が対数的に複雑な検索)。


std :: mapはバイナリツリーを使用して実装されているため、技術的にはバイナリ検索は実行されません。
jupp0r 2015年

11
@ jupp0r:範囲をバイナリ検索ツリーとして構造化することは、範囲全体のバイナリ検索を実装するための特定の方法です。「バイナリ検索」は、特定の実装というよりは抽象的な概念です。オフセットを配列にジャンプするか、リンクノードをたどるかは関係ありません。これらは、「範囲を二分する」ための特定の方法にすぎません。
Kerrek SB 2015

1
私はこれが古い記事であることを知っていますが、明確にするために「効率的な検索」は相対的です。技術的にstd::unordered_mapは、O(1)の検索時間がより効率的になります。の利点std::mapは、キーの順序付けにありますが、ルックアップにはありません。
アダムジョンストン

42

これは、C ++標準の連想コンテナ要件によって保証されています。たとえば、C ++ 11の23.2.4 / 10を参照してください。

連想コンテナの反復子の基本的な特性は、
降順でないキーの順序でコンテナを反復処理します。
非降順は、それらを構築するために使用された比較によって定義されます。
iからjまでの距離が次のような任意の2つの逆参照可能な反復子iおよびjの場合
ポジティブ、
  value_comp(* j、* i)== false

および23.2.4 / 11

より強い条件が保持する一意のキーを持つ連想コンテナの場合、
  value_comp(* i、* j)!= false。

32

データ構造に混乱があると思います。

ほとんどの言語では、a mapは単なるAssociativeContainerです。キーを値にマップします。「新しい」言語では、これは一般にハッシュマップを使用して行われるため、順序は保証されません。

ただし、C ++ではそうではありません。

  • std::mapあるソート連想コンテナ
  • std::unordered_map C ++ 11で導入されたハッシュテーブルベースの連想コンテナ

したがって、注文時の保証を明確にするために。

C ++ 03の場合:

  • std::setstd::multisetstd::map及びは、std::multimapキー(および基準供給さ)に従って順序付けされることが保証され
  • std::multisetstd::multimap、標準では同等の要素に任意の順序保証が課さない(すなわち、等しいとするもの)

C ++ 11の場合:

  • std::setstd::multisetstd::map及びは、std::multimapキー(および基準供給さ)に従って順序付けされることが保証され
  • std::multisetstd::multimap、標準課すその同等の要素(等しい比較するもの)をその挿入順に従って順序づけられる(第一最初に挿入)
  • std::unordered_*コンテナは、その名前が示すように、注文されていません。特に、要素の順序、コンテナが変更(挿入/削除)されると変更されるます。

要素が順序付けられていると規格が述べている場合、それは以下を意味します:

  • 反復すると、定義された順序で要素が表示されます
  • 逆方向に反復すると、要素が逆の順序で表示されます

これで混乱が解消されることを願っています。


これは私の質問とは何の関係もありません。申し訳ありません:)私はどちらが注文され、どちらが注文されたかを知っています-そうではありません。そして、要素を繰り返し処理するときは、順序を尋ねます。
キリルキーロフ

10
@KirilKirov:まあ、順序付けられた連想コンテナの定義は、それを反復するときに要素が順序付けられるということです。
Matthieu M.

まあ、私はあなたが正しいと思いますが、私はそれを知りませんでした、そしてそれはまさに私が尋ねていたものです:)
キリルキーロフ

4

これは234を出力することが保証されていますか、それとも実装が定義されていますか?

はい、提供さstd::mapれたKeyでによって注文された、ソートされたコンテナComparatorです。したがって、保証されています。

具体的なint値よりも大きいキーを使用して、すべての要素を反復処理したいと思います。

それは確かに可能です。


3

はい...の要素にはstd::map厳密な弱順序があります。つまり、要素はセットで構成され(つまり、「等しい」キーの繰り返しはありません)、等しいかどうかは、 2つのキーAとB。キーAがキーB以上、BがA以上の場合、キーAはキーBと同じです。

そうは言っても、std::mapその型の弱い順序付けがあいまいである場合、aの要素を適切に並べ替えることはできません(あなたの場合、整数をキー型として使用しているので問題ありません)。のキーに使用しているタイプの全体的な順序を定義する操作を定義できる必要がありますstd::map。そうでない場合、要素の部分的な順序のみ、またはAと比較できないプロパティを持つposetのみが存在します。 B.このシナリオで通常発生するのは、キーと値のペアを挿入できることですが、マップ全体を反復したり、「欠落」を検出したりすると、キーと値のペアが重複する可能性があります。std::map::find()マップで特定のキー/値ペアを実行しようとしたときのキー/値ペア。


他の答えとして、これは実際に私の質問に答えるものではありません。とにかくありがとうございます。
キリルキーロフ

-3

begin()は最小の要素を提供します。しかし、それは実装に依存しています。C ++標準で指定されていますか?そうでない場合、この仮定を行うことは危険です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.