map
文章目录
map介绍
map 字典 映射
map是一个关系式容器 ,以模板(泛型)方式实现
底层通常是由一颗红黑树组成
第一个可以称为键(key)
第二个可以称为该键的值(value)
在map内部所有的key都是有序的,并且不会有重复的值
map的特点
map是一个容器,容器里面存放元素,把这个元素分成两个逻辑区块
- 第一个称为键(key) 每个*键(key)*只能在map中出现一次,并且会进行有序的排列
- 第二个称为该键值(value),这两个区块当成一个组来进行管理
- 每一个节点的内容是由一个pair<key,value>构成。
key和value 的条件
- key是唯一的,不重复的,里面的key会自动去除重数据
- map会根据key的值自动的进行一个排序
- 每个key对应着一个value
map的基本操作
map
中每个键值对称之为节点
#include <map> //导入头文件
map的存放的节点容器时一个pair
的类
节点pair
原型
template <typename K,typename V>
class pair{
public:
K first; //key的值
V seconed; //value的值
pair(K& first,V& seconed): first(first),seconed(seconed){
}
}
用法,pair节点通常是通过map返回的一数据类型
pair<T1, T2> p;
pair<T1, T2> p(v1, v2);
pair<T1, T2> p = {v1, v2}
make_pair(v1, v2);
初始化方式
map<模板1,模板2> 变量名
map<key,value> m; //定义了一个 m 的空对象
map聚合初始化方式初始化map
map<string,int> mymap = {
{ "alpha", 0 },
{ "beta", 1 },
{ "gamma", 2},
};
cout<<map["beta"]<<endl;
插入数据
m.insert(pair<k,v>(key,value)); //插入键值对 只负责插入数据,不进行修改数据
m.insert(make_pair(key,value)); //同上,该函数会自动识别类型
//c++11 新增加的插入方式
m2.insert({ key, value });
m.at(key); //访问和修改键值对,所以只负责查找数据和修改数据,不负责插入数据
//访问数据和
//修改键值
//如果不存在会自动插入一个新的元素进去
m[key]=value;
//KEY可以改吗
//可以删除一个Key,然后添加一个新的key
operator[] at() 的区别
-
相同点:都可以通过key的值访问value
-
不同点:at不能新增节点,如何节点不存在,则报错
[] 如果key的值不存在,则新创建一个节点
迭代器操作
- map迭代器不能进行
+
和-
运算符操作 - 可以使用
++
--
运算符进行遍历
map常见用途
- 需要建立字符串与整数之间映射关系
- 通过一个唯一的key来建立存储关系的
遍历方式
//for循环遍历
for(map<T1,T>::iterator iter=m.begin();iter!=end;iter++){
cout<<iter->first<<":"<<iter->seconed<<endl;
}
//foreach遍历
for (auto e:map){
cout<<e.first<<":"<<e.seconed<<endl;
}
map的基本操作函数
// 插入元素
void insert();
// 删除一个元素 参数是迭代器 通过find找到key的迭代器,然后删除
void erase(iterator iter);
// 查找一个元素 通过key的值查找 返回一个迭代器 ,如果没有找到的话会返回 end()
iterator find();
//通过key访问或修改数据 (不存在会报错)
Value at();
//修改数据,访问数据,插入数据 (不存在会自动创建)
Value operator [Key k];
iterator begin(); //返回指向map头部的迭代器
iterator end(); //返回指向map末尾的迭代器
reverse_iterator rbegin(); //返回一个指向map尾部的逆向迭代器
reverse_iterator rend(); //返回一个指向map头部的逆向迭代器
int size(); // 返回map中元素的个数
long max_size(); // 返回可以容纳的最大元素个数
void clear(); // 删除所有元素
void count(); // 返回指定key出现的次数 map中key只会出现一次,所以只会返回1或者是0
void empty(); // 如果map为空则返回true
void swap(); // 交换两个map
void lower_bound(); // 返回键值>=给定元素的第一个位置
void upper_bound(); // 返回键值>给定元素的第一个位置
void get_allocator(); // 返回map的配置器
void equal_range(); // 返回特殊条目的迭代器对
void key_comp(); // 返回比较元素key的函数 map中没有实现这个函数
void value_comp(); // 返回比较元素value的函数 map中没有实现这个函数
map的优缺点
- 优点:
- 有序性:map结构的红黑树自身是有序的,不停的插入数据,总是获取到一个有序的数据
- 时间复杂度低:内部结构时红黑树,红黑树很多操作都是在log(n)的时间复杂度下实现的,因此效率高。
- 缺点:空间占有率高:因为map内部实现是红黑树,每一个节点都需要额外保存,这样使得每一个节点都占用大量的空间。
multimap 多表映射
#include <map> //头文件
多表映射的结构与map 相似,但是多表映射可以允许有多个重复的键值
特点:
- key的值可以重复
- key的值仍然会进行排序
可以用做多个key时使用,由于会排序,所有key的位置都是连续的并排下去
在无序映射中不能进行直接的键值操作
at()
operator[]
不可以直接通过键的值进行访问
int count() //返回指定key出现的次数,multimap中key会出现多次
unordered_map 无序映射
英 [ˌʌnˈɔːdəd] 美[ʌnˈɔrdərd]
#include<unordered_map> //头文件
c++11以下的的版本使用 #include <hash_map>
特点:
- 无序映射的key的值不会进行排序,但是会去除重复的key值
- 优点:内部结构是哈希表,查找为O(1),效率高.
- 缺点:哈希表的建立耗费时间。
- 应用场景:对于频繁查找的问题,用unordered_map更高效.
- 底层:是一个哈希表完成的
- unordered_map记录元素的hash值,根据hash值判断元素是否相同
函数操作
unordered_map 函数操作基本上与map的值一致
只要注意unordered_map的key值不会排序就行
void bucket_count(); //返回槽(Bucket)数
void bucket_size(); //返回槽大小
void bucket(); //返回元素所在槽的序号
void rehash(); //设置槽数
void reserve(); //请求改变容器容量
unordered_multimap
无序多表映射
特点
- 该容器底层是哈希表实现
- 里面的key既不会去重,也不会排序
- 用法与unordered_map类似
- 虽然不会排序,但重复的数据也会排列在一起
总结
- map 的基本使用
- 四个容器之间的区别与特性
map
multimap
- ``unordered_map`
- unordered_multimap
扩展知识点
set 集合 //集合内的元素是不重复的 类似map中的key元素,但是没有对应的value
set<类型> s;
s.inert(10);//插入元素10
s.erase(10);//删除元素10
s.clear();//清空集合
s.size();//集合元素的个数
s.empty();//判断集合是否为空
集合不会被排序
unordered_set 无序集合 //底层实现哈希表(hash)实现的
unordered_set::insert
unordered_set::find
unordered_set::erase
multiset 集合数据可以重复
std::set<int> numbers {8, 7, 6, 5, 4, 3, 2, 1};
//set 对应map 去重排序
set<int> s = { 2, 5, 4, 7, 9, 6, 4, 3, 5, 8, 0, 5, 34, 23 };
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
//multiset 对应multimap 排序
multiset<int> ms = { 2, 5, 4, 7, 9, 6, 4, 3, 5, 8, 0, 5, 34, 23 };
for (auto e : ms)
{
cout << e << " ";
}
cout << endl;