C++关联容器

关联容器

  • 关联容器中的元素是按关键字保存和访问的,顺序容器中的元素按其在容器中的位置顺序保存和访问的
  • mapmultimap定义在头文件map中,setmultiset定义在头文件set中,无序容器定义在头文件unordered_mapunordered_set
  • 关联容器的迭代器都是双向的

关联容器概述

定义关联容器

  • 每个关联容器都定义了一个默认构造函数,其创建一个指定类型的空容器
map<string,size_t>word_count;//空容器
//列表初始化
set<string>exclude={"the","but","and","od","an","a"};
//三个元素:authors将姓映射为名
map<string,string>authors={{"Joyce","James"},{"Austen","Jane"},{"Dickens","Charles"}};
初始化multimap或multiset
  • 允许多个元素具有相同的关键字
//定义一个有20个元素的vector,保存0-9每个整数的两个拷贝
vector<int>ivec;
for(vector<int>::size_type i=0;i!=10;++i){
    ivec.push_back(i);
    ivec.push_back(i);
}
//iset保存来自ivec的不重复的元素,miset包含所有20个元素
set<int>iset(ivec.cbegin(),ivec.cend());
multiset<int>miset(ivec.cbegin(),ivec.cend());

pair类型

  • 头文件utility
  • 用来生成特定类型的模板,当创建一个pair时,必须提供两个类型名,pari的数据成员将具有对应的类型
  • pair的默认构造函数对数据成员进行值初始化
pair<string,string>anno;
pair<string,size_t>word_count;
pair<string,string>autohr{"James","Joyce"};
  • pair的数据成员时public,两个成员分别命名为firstsecond
创建pair对象的函数
pair<string,int>process(vector<string>&v){
    if(!v.empty())
        return {v.back(),v.back.size()};//列表初始化
    else
        return pair<string,int>();//隐式构造返回值
}

关联容器操作

  • 关联容器额外的类型别名
    • key_type此容器类型的关键字类型
    • mapped_type每个关键字关联的类型。只适用于map
    • value_type对于set,与key_type相同,对于map,为pair<const key_type,mapped_type>

关联容器迭代器

  • 当解引用一个关联容器迭代器时,会得到一个类型为容器的value_type的值的引用
//获得指向word_count中一个元素的迭代器
auto map_it = word_count.begin();
//*map_it是指向一个pair<const string,size_t>对象的引用
//无法改变关键字成员的值
set的迭代器是const
set<int>iset={0,1,2,3,4,5,6,7,8,9};
set<int>::iterator set_it = iset.begin();
if (set_it != iset.end()){
    //*set_it = 42;
    cout<<*set_it<<endl;
}
遍历关联容器
auto map_it = word_count.cbegin();
while(map_it != word_count.cend()){
    cout<<map_it->first<<"occurs"<<map_it->second<<"times"<<endl;
    ++map_it;
}

添加元素

  • 关联容器的insert成员向容器中添加一个元素或一个元素范围
vector<int>ivec={2,4,6,8,2,4,6,8};
set<int>set2;
set2.insert(ivec.cbegin(),ivec.cend());
set.insert({1,3,5,7,1,3,5,7});
向map添加元素
word_count.insert({word,1});
word_count.insert(make_pair(word,1));
word_count.insert(pair<string,size_t>(word,1));
word_count.insert(map<string,size_t>::value_type(word,1));
检测insert的返回值
  • 不包含重复关键字的容器,添加单一元素的insert和emplace版本返回一个pair,pair的first成员是一个迭代器,指向具有给定关键字的元素,second成员是一个bool值,指出元素是插入成功还是已存在于容器中。
map<string,size_t>word_count;
string word;
while(cin>>word){
    aito ret = word_count.insert({word,1});
    if (!ret.second)
        ++ret.first->second;
}
向multiset或multimap添加元素
multimap<string,string>authors;
authors,insert({"Barth,John","Sot-Weed FActor"});

删除元素

if (word_count.erase(removal_word))
    count<<"ok:"<<remove_word<<"removed\n";
else cout<<"oops:"<<removal_word<<"not found!\n";
//保存不重复关键字的容器,erase的返回值总是0或1,0表示删除的元素并不在容器中
//允许重复关键字的容器,删除元素的数量可能大于1
c.erase(k);
//从c中删除每个关键字为k的元素,返回一个size_type值,指出删除的元素的数量
c.erase(p);
//从c中删除迭代器p指定的元素,p必须指向c中一个真实元素,不能等于c.end(),返回一个指向p之后元素的迭代器,若p指向c中的尾元素,则返回c.end()
c.erase(b,e);
//删除迭代器对b和e所表示的范围中的元素,返回e

map的下标操作

  • map和unordered_map容器提供下标运算符和对应的at函数
  • map下标运算符接受一个索引,获取此关键字相关联的值,若关键字不在map中,会创建一个元素插入到map中,关联值将进行值初始化
map<string,size_t>word_count;
word_count["Anna"]=1;

//c[k];
//返回关键字为k的元素

//c.at(k);
//访问关键字为k的元素,带参数检查;若k不在c中,抛出一个out_of_range异常
使用下标操作的返回值
  • 对一个map进行下标操作时,会获得一个mapped_type对象

访问元素

//lower_bound与upper_bound不适用于无序容器
//下标和at操作只适用于非const的map和unordered_map

c.find(k);
//返回一个迭代器,指向第一个关键字为k的元素,若k不在容器中,则返回尾后迭代器

c.count(k);
//返回关键字等于k的元素的数量,对于不允许重复关键字的容器,返回值永远时0或1

c.lower_bound(k);
//返回一个迭代器,指向第一个关键字不小于k的元素

c.upper_bound(k);
//返回一个迭代器,指向第一个关键字大于k的元素

c.equal_range(k);
//返回一个迭代器pair,表示关键字等于k的元素的范围,若k不存在,pair的两个成员均等于c.end()

无序容器

  • 使用哈希函数和关键字类型的==运算符
unorder_map<string,size_t>word_count;
string word;
while(cin>>word)
    ++word_count[word];//提取并递增word的计数器
for(const auto &w:word_count)//对map中的每个元素
    cout<<w.first<<"occurs"<<w.second<<((w.second>1)?"times":"time")<<endl;
管理桶
  • 无序容器在存储上组织为一组桶,每个桶保存零个或多个元素。无序容器使用一个哈希函数将元素映射到桶。
  • 桶接口
    • **c.bucket_count()**正在使用的桶的数目
    • **c.max_bucket_count()**容器能容纳的最多的桶的数量
    • **c.bucket_size(n)**第n个桶中有多少个元素
    • **c.bucket(k)**关键字为k的元素在哪个桶中
  • 桶迭代
    • local_iterator可以用来访问桶中元素的迭代器类型
    • const_local_iterator桶迭代器的const版本
    • **c.cbegin(n),c.end(n)**桶n的首元素迭代器和尾后迭代器
    • **c.cbegin(n),c.ceng(n)**与前两个函数类似,但返回const_local_iterator
  • 哈希策略
    • **c.load_factor()**每个桶的平均元素数量,返回float值
    • **c.max_load_factor()**c试图维护的平均桶大小,返回float值,c会在需要时添加新的桶,以使得load_factor<=max_load_factor重组存储,使得bucket_count>=n
    • **c.rehash(n)**重组存储,使得bucket_count>=n,且bucket_count>size/max_load_factor
    • **c.reserve(n)**重组存储,使得c可以保存n个元素且不必rehash
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值