C++ STLでキーと値の属性を簡単に作成するには、マップとペアのセットの2つの方法があります。たとえば、私は持っているかもしれません
map<key_class,value_class>
または
set<pair<key_class,value_class> >
アルゴリズムの複雑さとコーディングスタイルの観点から、これらの使用法の違いは何ですか?
セット要素は、セット内にある間は変更できません。 set
のiterator
とconst_iterator
は同等です。したがって、set<pair<key_class,value_class> >
では、value_class
をインプレースで変更できません。セットから古い値を削除し、新しい値を追加する必要があります。ただし、value_class
がポインターの場合、これが指すオブジェクトを変更することを妨げるものではありません。
map<key_class,value_class>
を使用すると、マップへの非const参照があると想定して、value_class
をインプレースで変更できます。
それらは意味的に異なります。検討してください:
#include <set>
#include <map>
#include <utility>
#include <iostream>
using namespace std;
int main() {
pair<int, int> p1(1, 1);
pair<int, int> p2(1, 2);
set< pair<int, int> > s;
s.insert(p1);
s.insert(p2);
map<int, int> m;
m.insert(p1);
m.insert(p2);
cout << "Set size = " << s.size() << endl;
cout << "Map size = " << m.size() << endl;
}
出力:
セットサイズ= 2
マップサイズ= 1
基本的な違いは、セットの場合、キーはペアであるのに対し、マップの場合、キーはkey_classであるということです。これにより、マップで行いたいことであるkey_classによる検索が困難になります。
どちらも通常は同じデータ構造(通常は赤と黒のバランスのとれたバイナリツリー)で実装されるため、2つの複雑さは同じです。
map<key_class,value_class>
はkey_classでソートし、key_classの重複を許可しません。set<pair<key_class,value_class> >
は、key_classのインスタンスが等しい場合、key_class、次にvalue_classでソートし、key_classに複数の値を許可します
std::map
は、連想データ構造として機能します。つまり、関連付けられたキーを使用して値をクエリおよび変更できます。
std::set<pair<K,V> >
はそのように機能させることができますが、キーを使用してクエリの追加コードを記述し、値を変更するコードを追加する必要があります(つまり、古いペアを削除して、同じキーと別のペアを挿入します)値)。また、同じキーを持つ値が2つ以下であることを確認する必要があります(推測したとおり、コードが増えます)。
つまり、std::set
をstd::map
のように動作させることができますが、その理由はありません。
アルゴリズムの複雑さを理解するには、最初に実装を理解する必要があります。
std :: mapはRBツリーを使用して実装されますが、hash_mapはリンクリストの配列を使用して実装されます。 std :: mapは、挿入/削除/検索操作にO(log(n))を提供し、hash_mapはO(1)が最良のケースであり、o(n)ハッシュの衝突に応じて最悪の場合。