c++基础(五)——关联容器

1.关联容器

  关联容器中的元素时按照关键字来保存和访问的,与之相对的,顺序容器中的元素时按它们在容器中的位置来顺序保存和访问的。两个主要关联容器是 map 和 set。标准库提供了8个关联容器,这8个容器间的不同体现在
三个维度上:

  • 或是一个 map 或是一个 set
  • 或者要求不重复关键字,或者允许重复关键字
  • 按顺序保存元素,或无序保存

2.使用关联容器

  • map
  • 1 //统计每个单词在输入中出现的次数
    2 map<string, size_t> word_count;    //string到size_t的空map
    3 string word;
    4 while (cin >> word)
    5     ++word_count[word];    //提取word的计数器并将其加1
    6 for(const auto &w : word_count)    //对map中的每个元素
    7     //打印结果
    8     cout << w.first << " occurs " << w.second
    9          << ((w.second > 1)? " times ": "time") << endl;
  • set
  • 1 //统计输入中每个单词出现的次数
    2 map<string, size_t> word_count;    //string到size_t的空map
    3 set<string> exclude = {"The", "But", "And", "Or", "An", "A",
    4                "the", "but", "and", "or", "an", "a"};
    5 string word;
    6 while (cin >> word)
    7     //只统计不在exclude中的单词
    8     if (exclude.find(word) == exclude.end())
    9         ++word_count[word];    //获取并递增word的计数器

3.关联容器概述

  关联容器不支持顺序容器的位置相关操作,例如push_front或push_back。原因是关联容器中元素是根据关键字存储的,这些操作对关联容器没有意义。关联容器的迭代器都是双向的

  • 初始化 multimap 和 multiset。一个map或set中的关键字必须是唯一的,容器multimap和multiset没有此限制,它们允许多个元素具有相同的关键字。
  •  1 //定义一个有20个元素的vector,保存0到9每个整数的两个拷贝
     2 vector<int> ivec;
     3 for (vector<int>::size_type i = 0; i != 10; ++i){
     4     ivec.push_back(i);
     5     ivec.push_back(i);    //每个数重复保存一次
     6 }
     7 //iset包含来自ivec的不重复的元素,miset包含所有20个元素
     8 set<int> iset(ivec.begin(), ivec.end());
     9 multiset<int> miset(ivec.begin(), ivec.end());
    10 cout << ivec.size() << endl;    //打印出20
    11 cout << iset.size() << endl;    //打印出10
    12 cout << miset.size() << endl;    //打印出20

3.1 set,map自定义函数排序

  关联容器对其关键字类型有一些限制。对于有序容器,关键字类型必须定义元素比较的方法。默认情况下,标准库使用关键字类型<运算符来比较两个关键字。

  用来组织一个容器中元素的操作的类型也是该容器类型的一部分。为了指定使用自定义的操作,必须在定义关联容器类型时提供此操作的类型使用方法如下:用尖括号指定要定义的那种类型的容器,自定义的操作类型必须在尖括号中紧跟元素类型给出。例如:我们不能直接定义一个Sales_data的multiset,因为Sales_data没有<运算符。因此需要定义一个compareIsbn:

1 bool compareIsbn (const Sales_data &lhs, const Sales_data &rhs)
2 {
3     return lhs.isbn() < rhs.isbn();
4 }

  为了使用自己定义的操作,在定义multiset时我们必须提供两个类型:关键字类型Sales_data,以及比较操作类型——应该是一种函数指针类型,可以指向compareIsbn。

1 //bookstore中多条记录可以有相同的ISBN
2 //bookstore中的元素以ISBN的顺序进行排列
3 multiset<Sales_data, decltype(compareIsbn)*> bookstore(compareIsbn);

  此处,我们使用decltype来指出自定义操作的类型。记住,当用decltype来获得一个函数指针类型时,必须加上一个*来指出我们要使用一个给定函数类型的指针;用compareIsbn来初始化bookstore对象,这表示当我们想bookstore添加元素时,通过调用compareIsbn来为这些元素排序。

  下面举两个实例:均按照降序进行排列,容器默认是使用“<”。

 1 #include <set>
 2 #include <map>
 3 #include <vector>
 4 #include <string>
 5 #include <iostream>
 6 using namespace std;
 7 
 8 class st {
 9 public:
10     int id;
11     string name;
12     st(int id, string name);
13     ~st() {};
14 };
15 
16 st::st(int id, string name) :id(id), name(name) {
17 
18 }
19 
20 bool compareST(const int &s, const int &r) {
21     return s > r;
22 }
23 
24 bool compareST2(const st *s, const st *r) {
25     return s->id > r->id;
26 }
27 
28 int main()
29 {
30     /// map
31     st *st1 = new st(3, "st1");
32     st *st2 = new st(1, "st2");
33     st *st3 = new st(2, "st3");
34     
35     map<int, st*, decltype(compareST)*> temp(compareST);
36     temp.insert(make_pair(st1->id, st1));
37     temp.insert(make_pair(st2->id, st2));
38     temp.insert(make_pair(st3->id, st3));
39 
40     for (auto item : temp) {
41         cout << item.first << "\t" << item.second->name << endl;
42     }
43 
44     cout << "========================" << "\n";
45 
46     /// set
47     set<st*, decltype(compareST2)*> temp2(compareST2);
48     temp2.insert(st1);
49     temp2.insert(st2);
50     temp2.insert(st3);
51 
52     for (auto item : temp2) {
53         cout << item->id << "\t" << item->name << endl;
54     }
55     
56     getchar();
57     return 0;
58 }

  

猜你喜欢

转载自www.cnblogs.com/KongHuZi/p/11366383.html