有序关联容器

来源:互联网 发布:java工程师人才缺口 编辑:程序博客网 时间:2024/05/18 09:05

关联容器:

  • multi:允许关键字重复出现
  • unordered_:不保持关键字顺序存储
  • 支持的操作CP294
  • 双向迭代器
  • 通常不使用泛型算法,但可以使用只读的算法。(使用专用的find算法速度更快。)
  • 标准库默认使用<比较关键字的大小
    如果要使用自定义的比较操作,必须在定义时提供该操作的类型(放在关键字类型后面)
//类A没有<操作符bool compare(const A& a1,const A& a2);set< A,decltype(compare)* > book(compare);
  • 元素类型为pair的2个数据成员为public
    支持列表初始化
pair<string,int> author{"a",1};
map<string, size_t>word_count;//sting类型作为关键词,size_t类型作为值的类型string word;while (cin >> word)  ++word_count[word];for(const auto &w:word_count)    count<<w.first<<w.second<<endl;
  • key_type:关键字类型
    由于定义后无法改变,所以为const
  • 插入
    1.插入时可以是无序的
    2.容器会根据下标由大到小自动调整顺序

有序关联容器:

  • map
  • multimap
  • set
  • multiset

map(关联数组):

  • 关键字-值的集合,通过关键词(类似下标)来查找
  • 类pair有两个public成员
    • first为关键字,类似于数组的下标,初始化后无法改变
    • second为数组
//因为pair的键值是const的,所以范围for引用必须要加constfor (const pair<int, int>&p : mp)    cout << p.first << " " << p.second << endl;
  • 初始化
    • 建议使用make_pair构建
    • 即使输入了多个相同的关键字,但是只会保存1个
//值初始化map<string, int>mp = { {"aa", 1},                        {"aaa", 2},                        {"22", 33} };//必须用{key, value}包含起来map容器元素pair<string, int>p("aa", 1);pair<string, int>p={"aa", 1};
  • 插入CP384
    • 插入重复关键词的元素没有影响
    • 对于不包含重复关键字的关联容器,只插入1个元素的isert/emplace返回1个pair。
      first:迭代器
      second:成功为true,失败为false
mp.insert({ s2,b });//建议使用
map<string, size_t>mp;string word;while (cin >> word)    {    auto ret = mp.insert({ word,1 });    if (!ret.second)//出现重复        ++ret.first->second;//对map中对应的元素的内容+1  }//或者为while (cin >> word)    ++mp.insert({ word,0 }).first->second;

删除

  • 提供额外的版本(删除所有和给定关键字相同的元素)
size_t ret1 = mp.erase(2);//删除关键字为2的pair,返回被删除的个数
  • 同时提供迭代器版本和范围版本
auto ret2 = mp.erase(mp.begin());//删除迭代器指向的pair,返回指向下一个元素auto ret3 = mp.erase(mp.begin(), --mp.end());//删除范围不包括--mp.end(),返回--mp.end()

下标操作

  • map和unordered_map支持
mp[9] = 3;//如果下标(关键字)不存在,会自动插入该元素mp.at(3) = 2;
  • 返回类型为mapped_type(关键字的关联的类型,左值,可以读写 )不同于解引用的迭代器的返回类型value_type(容器所对应的pair类型)

访问

  • 对于不允许重复关键字的容器,建议使用find
  • 对于允许重复关键字的容器,可以同时使用find和count
map<int, int>mp = { { 1,1 },{ 2,2 },{ 3,3 },{ 4,4 },{ 5,5 } };auto ret1 = mp.find(1);//返回一个迭代器  auto ret2 = mp.find(11);//未找到,返回迭代器=mp.end();  auto ret3 = mp.count(1);//返回数量  auto ret4 = mp.count(11);
  • 对于允许重复关键字的容器,可以使用lower_bound和upper_bound确定范围
//返回的迭代器指向第一个关键字等于2的元素。auto ret5 = mp.lower_bound(2);  /*返回的迭代器指向第一个关键字大于3的元素,即最后1个为该关键字之后的元素*/auto ret6 = mp.upper_bound(3);/*如果该元素不存在,则lower_bound和upper_bound返回相同的迭代器,指向不影响容器的位置*/
for (auto beg = mmp.lower_bound(1), end = mmp.upper_bound(1); beg != end; ++beg)    cout << beg->first << " " << beg->second << endl;
  • 对于允许重复关键字的容器,可以使用equal_range确定范围
for (auto pos = mmp.equal_range(1), pos.first! = pos.second; ++pos.first)    cout << pos.first->second << endl;

示例:CP391

大小比较
1.依次比较first和second成员
2.两个比较的关系为与
3.记得带括号

cout << (p2 < p3) << endl;  cout << (p2 == p3) << endl;cout << (p2 != p3) << endl;

set:关键词的集合

  • 用于检查值是否存在
  • key_type和value_type一样都是关键字类型
  • 由于关键字类型定义后无法改变,所以set的迭代器只能访问元素
#include <set>//只保存关键字的容器

1.只存储关键字
2.只读

set<int>iset = { 0,1,2 };iset.insert({ 1,2,3,4,5,6,7 });

find函数返回一个指向给定关键字/(找不到)尾后迭代器。

if( iset.find(i)==iset.end() )
//迭代器auto set_it = iset.begin();cout << *set_it << endl;set<int>iset = { 0,1,2 };
int num = 2//找到后会返回指向该关键字的迭代器,否则返回尾后迭代器if (iset.find(num) == iset.end())auto map_it = mp.begin();while (map_it != mp.end())     cout << map_it->first << map_it->secod << endl;