目录
###map和set很多地方相似,最大的不同就是map中存放的不仅仅是key,还有value;使用map时,一般都是通过key去寻找value;

- map的第二个参数需要时我们自己写仿函数,第三个参数写了内存池需要我们自己写,默认表示内存从空间适配器上面申请;一般来说后面两个参数不需要我们自己写;
- map底层是红黑树,增删查改的时间复杂度是O(logN);
- map迭代器是按中序遍历的,所以按照key来排序是升序排列的。
一、map中实际的数据类型pair以及对应的数据打印
1、pair数据类型

key_type就是key,mapped_type就是value,而value_type才是底层每个数据的类型,这个value_type就是pair(对),这个对就是一个类,类里面有两个成员变量,就是key和value;
typedef pair<const Key, T> value_type;
template <class T1, class T2>
struct pair
{
typedef T1 first_type;
typedef T2 second_type;
T1 first;
T2 second;
pair() : first(T1()), second(T2())
{}
pair(const T1& a, const T2& b) : first(a), second(b)
{}
template<class U, class V>
pair(const pair<U, V>& pr) : first(pr.first), second(pr.second)
{}
};
template <class T1, class T2>
inline pair<T1, T2> make_pair(T1 x, T2 y)
{
return (pair<T1, T2>(x, y));
}
key就是first不可改变,否则会破坏底层构建规则;value(second)可以改变;
2、数据打印
由于map数据类型是pair,而这个类类型中没有实现流插入和流提取的重载,所以不能直接输出;所以这里使用到 . 和 -> ,key被重命名为first,value被重命名为second;用迭代器输出时迭代器重载了->和*,可以找到pair类型的对象指针和对象,然后再解引用;
###代码示例:
void test4()
{
map<string, string> m1;
m1.insert({ {"apple","苹果"},{"banana","香蕉"},{"pear","梨子"} });
map<string, string>::iterator i = m1.begin();
//1、* 解引用迭代器获得pair对象,通过pair的.去获取key和value
while (i != m1.end())
{
cout << (*i).first << " : " << (*i).second << endl;
i++;
}
cout << endl;
//2、-> 解引用获得获得pair对象指针,通过pair的-> 去获取key和value
i = m1.begin();
while (i != m1.end())
{
//->在迭代器中被重载,实际上是这样:
//i.operator->()->first
cout << i.operator->()->first << " : " << i->second << endl;
i++;
}
}
二、map的插入insert
1、插入数据时,数据的几种写法
void test1()
{
map<string, string> m1;
//map中数据类型就是pair
//插入
//1、可以插入一个 pair 的有名对象
pair<string, string> p1("auto", "自动");
m1.insert(p1);
//2、插入 pair 的匿名对象
m1.insert(pair<string, string>("left", "左"));
//3、插入pair的两个参数,插入过程中会发生隐式类型转换,先构造一个pair再插入
m1.insert({ "right","右" });
}
2、插入的几种写法
插入数据是按照key值是否相同插入的,有重复的就不会插入;
single element (1) pair<iterator,bool> insert (const value_type& val); template <class P> pair<iterator,bool> insert (P&& val);with hint (2) iterator insert (const_iterator position, const value_type& val); template <class P> iterator insert (const_iterator position, P&& val);range (3) template <class InputIterator> void insert (InputIterator first, InputIterator last);initializer list (4) void insert (initializer_list<value_type> il);
- 插入单个数据 ;
- 在指定的迭代器位置插入数据;
- 插入一段迭代器区间,插入会按照key排序;
- 插入一段列表;
###代码示例:
void test2()
{
map<string, int> mymap;
//1、插入单个数据
mymap.insert({ "one", 1 });
//2、在指定位置插入数据
map<string, int>::iterator it = mymap.end();
mymap.insert(it, { "two",2 });
//3、插入一段迭代器区间
map<string, int> mymap2;
mymap2.insert({ "three",3 });
mymap2.insert({ "four" ,4 });
mymap2.insert({ "five" ,5 });
mymap.insert(mymap2.begin(), mymap2.end());
//4、插入一段列表
mymap.insert({ { "six",6 } ,{"seven",7} });
}
3、插入单个值的返回值
插入单个值的返回值的类型是pair<iterator,bool>,这个类型的意思:
- iterator就是插入数据成功时数据的迭代器所在,这个key已经存在就插入失败,那么iterator就是这个已经存在的key的迭代器;
- bool插入成功就是true,插入失败就是false。
这个返回值是为了map的[]准备的,后面提及。
三、map的构造
// empty (1) ⽆参默认构造explicit map (const key_compare& comp = key_compare(),const allocator_type& alloc = allocator_type());// range (2) 迭代器区间构造template <class InputIterator>map (InputIterator first, InputIterator last,const key_compare& comp = key_compare(),const allocator_type& = allocator_type());// copy (3) 拷⻉构造map (const map& x);// initializer list (5) initializer 列表构造map (initializer_list<value_type> il,const key_compare& comp = key_compare(),const allocator_type& alloc = allocator_type());
- 无参构造不需要传参数,后面两个参数一般不用传;
- 迭代器区间构造,传入一段迭代器区间进行构造,左闭右开;
- 拷贝构造,传入一个map的对象进行构造;
- 列表构造,传入一段列表
map和set一样是双向迭代器,支持加加和减减以及反向迭代器;
###代码示例:
void test3()
{
//1、无参
map<int, int>m1;
//2、迭代器区间构造
map<int, int> m2;
m2.insert({ { 1,1 }, { 2,2 }, { 3,3 } });
map<int, int>m3(m2.begin(), m2.end());
//3、拷贝构造
map<int, int> m4(m2);
//4、列表构造
map<int, int>m5({ {5,5},{6,6},{7,7} });
}
四、map的删除查找以及其他常用接口
1、删除erase
| (1) | iterator erase (const_iterator position); |
|---|---|
| (2) | size_type erase (const key_type& k); |
| (3) | iterator erase (const_iterator first, const_iterator last); |
- 删除迭代器指定的位置;
- 给定key值,删除和含相同key值的数据,返回值是删除的个数;这里删除成功只会返回1,multimap返回的值可以是其他值,因为它支持存放多个相同key值的数据;
- 删除一段迭代器区间的数据
2、查找find
iterator find (const key_type& k);
const_iterator find (const key_type& k) const;
查找成功返回查找得到数据的迭代器;
3、count
size_type count (const key_type& k) const;
寻找含相同key值的数据,并且返回寻找到的个数;
4、lower_bound和upper_bound
iterator lower_bound (const key_type& k); const_iterator lower_bound (const key_type& k) const;iterator upper_bound (const key_type& k); const_iterator upper_bound (const key_type& k) const;
和set相同;
lower_bound返回大于等于这个数据的迭代器;upper_bound返回大于这个数据的迭代器。
五、map中的[]重载
// operator 的内部实现mapped_type& operator [] ( const key_type& k){// 1、如果k不在map中,insert会插⼊k和mapped_type默认值,同时[]返回结点中存储mapped_type值的引⽤,那么我们可以通过引⽤修改返映射值。所以[]具备了插⼊+修改功能// 2、如果k在map中,insert会插⼊失败,但是insert返回pair对象的first是指向key结点的迭代器,返回值同时[]返回结点中存储mapped_type值的引⽤,所以[]具备了查找+修改的功能pair<iterator, bool > ret = insert ({ k, mapped_type () });iterator it = ret.first;return it->second;}
前面学到的[]是通过下标获取数据,这里意义不同;
#代码示例:
void test5()
{
string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜",
"苹果", "香蕉", "苹果", "香蕉" };
map<string, int> m1;
for (const auto& i : arr)
{
m1[i]++;//没有就插入,并且返回value并且加加;有就返回value并且加加
}
for (const auto& j : m1)
{
cout << j.first << " 个数:" << j.second << endl;
}
}

6143

被折叠的 条评论
为什么被折叠?



