个人主页:Lei宝啊
愿所有美好如期而遇
目录
前言:
SGI-STL中关于键值对的定义:
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)
{}
};
typedef pair<const key, T> value_type;
先对pair了解一下,后面我们会用到。
同时要提到的是,接下来我们要介绍的四个关联性容器底层都是红黑树,即平衡搜索树,容器中的元素是一个有序的序列。
set
我们使用set时,只需要插入value一个值,但实际上底层是<value,value>构成的键值对。
set中元素不会重复,所以他具有去重功能。
set中元素不可修改(为了保证不破坏set元素的有序性),但是可以插入一个新元素或者删除元素。
set在进行遍历时默认是中序遍历,同时排列方式默认是less,也就是升序排列。
set的构造
第一种是构造一个空的set
第二个是用(first,last) 区间的元素进行构造
第三个是拷贝构造
set的迭代器
前两个是普通迭代器,加上r表示反向迭代器,加上c表示const迭代器。
这里我们简单介绍使用set的普通迭代器,他的原理及反向迭代器我们在这里说过:迭代器理解及模拟https://blog.csdn.net/m0_74824254/article/details/135838211?spm=1001.2014.3001.5501
#include <iostream>
#include <set>
using namespace std;
int main()
{
int array[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0, 1, 3, 5, 7, 9, 2, 4,6, 8, 0 };
set<int> st(array, array + sizeof(array) / sizeof(array[0]));
set<int>::iterator it = st.begin();
while (it != st.end())
{
cout << *it << " ";
it++;
}
cout << endl;
return 0;
}
set方法
insert
pair<iterator,bool> insert (const value_type& val)
insert返回值为pair<iterator,bool>类型,我们试着使用一下:
pair<set<int>::iterator, bool> p = st.insert(100);
cout << *(p.first) << " " << p.second << endl;
p.first得到st中指向100的迭代器,解引用得到100这个值,p.second得到bool值,这个值表征插入是否成功。
分两种情况:
- 没有这个值,插入成功,返回这个值的迭代器,bool值为true
- 有这个值,插入失败 ,返回这个值的迭代器,bool值为false
erase
st.erase(100);
set<int>::iterator it2 = st.find(1);
st.erase(it2);
count
返回set中值为x的元素的个数,实际上在set中这个方法用途就是判断元素在不在,在就是1,不在就是0。
lower_bound && upper_bound
iterator lower_bound (const value_type& val) const;
返回大于等于x的值的位置
iterator upper_bound (const value_type& val) const;
返回大于x的值的位置
我们结合两者一起来看:
删除了[1,6)范围内的值,右边界要大于5,set中大于5的最近的值为6。
multiset
与set不同的是insert返回值不同,同时multiset允许插入相同的值,无法去重。
我们简单使用一下:
map
键值对<key,T>,Compare比较时根据key进行比较,和T没有关系
map支持[]运算符重载,在[]中填入key,就可以找到对应的值。
map中的key唯一,不可修改。
map的构造
同set,不解释。
map的迭代器
也是同set
map方法
insert
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main()
{
map<string, string> m;
m.insert(pair<string, string>("apple", "苹果"));
m.insert(make_pair("banana", "香蕉"));
m.insert({ "fruit","水果" });
for (auto& e : m)
{
cout << e.first << " : " << e.second << endl;
}
cout << endl;
return 0;
}
[]运算符重载
mapped_type& operator[] (const key_type& k);
key_type就是key,mapped_type就是T(value),也就是说可以通过key去寻找到value,同时,如果这个key不存在,则创建一个key,value如果没有,则采取默认值。
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main()
{
string s[] = { "香蕉" ,"苹果","葡萄" };
map<string, int> m;
for (auto& e : s)
{
m[e]++;
}
for (auto& e : m)
{
cout << e.first << " " << e.second << endl;
}
cout << endl;
return 0;
}
我们尝试探究一下operator[]的实现原理:
(*((this->insert(make_pair(k,mapped_type()))).first)).second
首先make_pair就是构造一个pair<k,mapped_type>类型的对象,然后将他插入this指向的map对象中,insert返回值是pair<iterator,bool>,这里的迭代器理所当然就是map对象的迭代器(由map对象调用的insert方法),first也就取到了这个迭代器,这个迭代器的类型是pair*类型,指向pair<k,mapped_type>类型的对象,解引用取second就是得到value值,也就是operator[]返回值的引用。
multimap
这里允许插入相同key的键值对,其他类似于multiset。