1.关联容器
1.1分类
容器 | 模板 | 特点 |
---|---|---|
映射容器 | map | 一对多映射,基于关键字快速查找,不允许重复值 |
多重映射容器 | multimap | 一对多映射,基于关键字快速查找,允许重复值 |
集合容器 | set | 快速查找,不允许重复值 |
多重集合容器 | multiset | 快速查找,允许重复值 |
2map 容器
2.1概念
1:map: 是key-value构成的集合,key必须唯一。 映射是关联容器,它存储由键值和映射值组合而成的元素,
2:map主要用来查找key对应value,要求key必须是可排序的,键值通常用于排序和唯一标识元素必须支持**<比较运算符**。
3:map默认是以key升序存放键值对<key,value>数据,比较适合二分查找映射通常实现为二进制搜索树。。
4:映射容器通过键访问单个元素的速度通常比无序的映射容器慢,但它们允许基于子集的顺序直接迭代。
5:映射中的映射值可以使用括号运算符((operator[])通过其对应的键直接访问。
2.2map内部结构
1:map使用pair<key,value>类模板保存key与value,
2:pair<key,value>有两个public成员变量 :first和second,first存放key,second存放value。
3:在map里面可以使用map<>::value_type表示pair<key,value>。
因为:
typedef pair<key,value> value_type;
2.3 初始化
3种方式
//1默认构造(可带参数)
map<string,string> dict;
dict["apple"]="苹果";
dict["orange"]="橙子";
dict["banana"]="香蕉";
//2复制构造
map<string,string> dict1(dict)
//3范围赋值构造
std::map<char,int> first;
first['a']=10;
first['b']=30;
first['c']=50;
first['d']=70;
std::map<char,int> second (first.begin(),first.end());
初始化时必须给map<>类模板同时设置key与value的类型模板实参。
实参类型不限于基本类型、类类型(class、struct、union),还可以是容器模板。
2.4 基本操作
迭代器
2.5添加数据/
1:insert插入pair<>数据
map<string,string> dict;
//添加数据
dict["apple"]="苹果";
dict["orange"]="橙子";
dict["banana"]="香蕉";
cout<<dict["apple"]<<endl;
dict.insert(pair<string,string>("watermalon","西瓜"));
dict.insert(make_pair("watermalon","西瓜"));
//当dict中没有UFO这个值 系统就是自动创建一个UFO值的pair放进map中
//dict["UFO"];
解决方法:
//先查找有没有UFO 在进行【】操作
if(dict.count("UFO")!=0&&dict["UFO"=="?????"])
2:insert插入map<>::value_type成员数据
//map<string,string>::value_type和pair<string,string>一样
m.insert(map<int,int>::value_type(i,i*10));
3: insert插入make_pair数据
make_pair是一个函数模板,类似与如下实现:
template<class K,class V)
inline pair<K,V> make_pair(K const& k,V const& v){
return pair<K,V>(k,v);
}
dict.insert(make_pair("watermalon","西瓜"));
4: 下标运算符[]添加数据
map<string,string> dict;
//添加数据
dict["apple"]="苹果";
dict["orange"]="橙子";
dict["banana"]="香蕉";
2.6 遍历
迭代器for循环
//遍历
map<string,string>::iterator it=dict.begin();
while(it!=dict.end()){
cout<<it->first<<","<<it->second<<endl;
it++;
}
for_each()循环
void Print(const pair<string,string>& p){
cout<<p.first<<","<<p.second<<endl;
}
for_each(dict.begin(),dict.end(),Print);
最简单写法: C++11 for-loop-scope迭代器写法
for(auto p : m){
cout << "[" << p.first << "]=" << p.second << endl;
}
2.7查找
//count()判断key是否存在
if(m.count(key) == 1){
...
}
//find()判断key是否存在以及位置
map<int,int>::iterator it = m.find(key);
if(m.end() != it){
...
}
//下标运算符[]
m[key];//如果key不存在,默认创建。
2.8 删除
//删除
dict.erase("apple");
//迭代器删除
m.erase(m.begin());
//区域删除
m.erase(it_a,it_b);
2.9排序
默认按照key升序排列。自定义排序是,可以在实例化加上key的comp仿函数, 重载<运算符。
//意思是 如果类型为类 其升序有自己的定义方法那要不定义comp仿函数 要不定义<重载运算符
map<key类型,value类型,comp> m;
3set
3.1
1“:集合是按照特定顺序存储唯一元素的容器。
2:在集合中,元素的值还标识它(该值本身就是类型T的键),并且每个值都必须是唯一的。集合中元素的值不能在容器中修改一次(元素总是常量),但可以从容器中插入或移除。
3:在内部,集合中的元素总是按照其内部比较对象(类型为Compare)指示的特定严格弱排序条件进行排序。
4:集合容器访问单个元素的键通常比无序集合容器慢,但它们允许基于其顺序对子集进行直接迭代。
5:集合通常实现为二进制搜索树。
3.2基本和map相同
set,map的key会自动排序和去重
#include<iostream>
#include<set>
#include<vector>
#include<algorithm>
using namespace std;
/*set特点
* 1:升序
* 2:每个值唯一 不重复
* 3:每个都是确定的
*
*
* */
void Print(int n){
cout<<n<<" ";
}
int main(){
int arr[]={3,2,1,5,6,8,7};
set<int> s(arr,arr+7);
for_each(s.begin(),s.end(),Print);
cout<<endl;
//判断值出现过一次的数
int arr1[]={3,3,1,5,5,8,8};
vector<int> v(arr1,arr1+7);
set<int> s1;
for(int i=0;i<v.size();++i){
if(s1.count(v[i])==0){
s1.insert(v[i]);
}else{
s1.erase(v[i]);
}
}
cout<<*s1.begin()<<endl;
}