pair数据类型 关联式容器存储的是“键值对”形式的数据,其中第一个元素作为键(key),第二个元素作为值(value)。键值对”并不是普通类型数据,C++ STL 标准库提供了 pair 类模板,其专门用来将 2 个普通元素 first 和 second(可以是 C++ 基本数据类型、结构体、类自定的类型)创建成一个新元素<first, second>
。
pair 类模板定义在<utility>
头文件中。
1 2 3 4 #include <utility> pair<string, double > pair1;pair<string, double > pair2 ("h" , 0.3 ) ;pair<string, double > pair3 (pair2) ;
关联式容器 map http://c.biancheng.net/view/7173.html
map 容器存储的都是 pair 对象,也就是用 pair 类模板创建的键值对。其中,各个键值对的键和值可以是任意数据类型,包括 C++ 基本数据类型(int、double 等)、使用结构体或类自定义的类型。
通常情况下,map 容器中存储的各个键值对都选用 string 字符串作为键的类型。
与此同时,在使用 map 容器存储多个键值对时,该容器会自动根据各键值对的键的大小,按照既定的规则进行排序。默认情况下,map 容器选用std::less<T>
排序规则(其中 T 表示键的数据类型),其会根据键的大小对所有键值对做升序排序。当然,根据实际情况的需要,我们可以手动指定 map 容器的排序规则,既可以选用 STL 标准库中提供的其它排序规则(比如std::greater<T>
),也可以自定义排序规则。
另外需要注意的是,使用 map 容器存储的各个键值对,键的值既不能重复也不能被修改。换句话说,map 容器中存储的各个键值对不仅键的值独一无二,键的类型也会用 const 修饰,这意味着只要键值对被存储到 map 容器中,其键的值将不能再做任何修改。
前面提到,map 容器存储的都是 pair 类型的键值对元素,更确切的说,该容器存储的都是 pair<const K, T> 类型(其中 K 和 T 分别表示键和值的数据类型)的键值对元素。
引入:
1 2 #include <map> using namespace std;
map容器的模板定义如下:
1 2 3 4 5 template < class Key , class T , class Compare = less<Key>, class Alloc = allocator<pair<const Key,T> > > class map;
可以看到,map 容器模板有 4 个参数,其中后 2 个参数都设有默认值。大多数场景中,我们只需要设定前 2 个参数的值,有些场景可能会用到第 3 个参数,但最后一个参数几乎不会用到。
1 2 3 4 5 6 7 #include <map> using namespace std; map<string, int > m; map<string, int > m{{"a" ,1 },{"b" ,2 }}; map<string, int > m{make_pair ("a" , 1 ), make_pair ("b" , 2 )};
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 m.insert ({"a" , 1 }); m.insert (make_pair ("a" , 1 )); m.insert (pair <string, int >("a" , 1 )); m["a" ] = 1 ; m.emplace ("a" , 1 ); iter = m.find ("a" );if (iter != m.end ()) cout << "have found" ; num = m.count ("a" ); iter = m.find ("a" ); m.erase (iter); m.erase (m.begin (), m.end ()); m.erase ("a" ); m.clear (); m.begin (); m.size (); m.max_size (); m.empty ();
关联式容器 set 使用 set 容器存储的各个元素的值必须各不相同。更重要的是,从语法上讲 set 容器并没有强制对存储元素的类型做 const 修饰,即 set 容器中存储的元素的值是可以修改的。但是,C++ 标准为了防止用户修改容器中元素的值,对所有可能会实现此操作的行为做了限制,使得在正常情况下,用户是无法做到修改 set 容器中元素的值的。
对于初学者来说,切勿尝试直接修改 set 容器中已存储元素的值,这很有可能破坏 set 容器中元素的有序性,最正确的修改 set 容器中元素值的做法是:先删除该元素,然后再添加一个修改后的元素。
值得一提的是,set 容器定义于<set>
头文件,并位于 std 命名空间中。
set 容器的类模板定义如下:
1 2 3 4 template < class T , class Compare = less<T>, class Alloc = allocator<T> > class set;
注意,由于 set 容器存储的各个键值对,其键和值完全相同,也就意味着它们的类型相同,因此 set 容器类模板的定义中,仅有第 1 个参数用于设定存储数据的类型。
对于 set 类模板中的 3 个参数,后 2 个参数自带默认值,且几乎所有场景中只需使用前 2 个参数,第 3 个参数不会用到。
1 2 3 4 5 6 #include <set> using namespace std; set<string> myset; set<string> myset{"a" , "b" , "c" };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 myset.insert ("d" ); myset.emplace ("d" ); iter = myset.find ("a" );if (iter != myset.end ()) cout << "have found" ; num = myset.count ("a" ); iter = myset.find ("a" ); myset.erase (iter); myset.erase (m.begin (), m.end ()); myset.erase ("a" ); myset.clear (); myset.begin (); myset.size (); myset.max_size (); myset.empty ();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 struct ListNode { int val; ListNode *next; ListNode (int x) : val (x), next (NULL ) {} friend bool operator < (const shared_ptr<ListNode> &p1, const shared_ptr<ListNode> &p2) { return p1->val < p2->val; } friend bool operator > (const shared_ptr<ListNode> &p1, const shared_ptr<ListNode> &p2) { return p1->val > p2->val; } };struct cmp { bool operator () (ListNode* const &p1, ListNode* const &p2) { return p1->val < p2->val; } };void test_set2 () { int a[] = {5 , 3 , 8 , 1 ,9 }; auto phead = new ListNode (-1 ); auto p = phead; for (auto &v: a) { p->next = new ListNode (v); p = p->next; } set<ListNode*, cmp> ms; p = phead->next; while (p) { ms.insert (p); p = p->next; } for (auto & v: ms) { cout << v->val << " " ; } }void test_set3 () { int a[] = {5 , 3 , 8 , 1 ,9 }; auto phead = make_shared <ListNode>(-1 ); auto p = phead; set<shared_ptr<ListNode>> ms; for (auto &v: a) { auto temp = make_shared <ListNode>(v); auto mp = p.get (); mp->next = temp.get (); p = temp; ms.insert (temp); cout << temp.get ()->val << " " << temp.get () << endl; } cout << endl; for (auto & v: ms) { cout << v->val << " " << v->next << "\n" ; } }void test_set4 () { int a[] = {5 , 3 , 8 , 1 ,9 }; auto phead = new ListNode (-1 ); auto p = phead; for (auto &v: a) { auto temp = new ListNode (v); p->next = temp; p = p->next; cout << temp->val << " " << temp << endl; } cout << endl; set<shared_ptr<ListNode>> ms; p = phead->next; while (p) { auto temp = shared_ptr <ListNode>(p); ms.insert (temp); p = p->next; } for (auto & v: ms) { cout << v->val << " " << v->next << "\n" ; } }