目录
set使用
set的模板参数
构造函数
成员函数 insert
iterator
编辑
find
count
pair
pair 的模板参数
make_pair
multiset使用
multiset 的模板参数
set 与 multiset 的区别
count
map使用
map 的模板参数
构造函数
insert
iterator
find
编辑
count
operator[]
multimap使用
multimap与map 的区别
set使用
set的模板参数
set 是一个 key 模式的结构,底层使用的是红黑树。
set 可以给一个类型,由于底层使用的是红黑树,所以 key 一定要支持比较,所以还有一个 compare的模板参数,这里可以给仿函数类型,还有一个就是空间配置器,空间配置器我们不多说。
构造函数
构造函数,我们常用的就是一个空的构造,或者是用一段迭代器区间来构造。
vector<int> v{ 1,2,3,4,5,6,7,8,9 };set<int> se(v.begin(), v.end());
这样就构造好了,当然任何迭代器都可以。
那么我们遍历一下。
for (auto e : se)cout << e << " ";cout << endl;
这里我想应该都能看明白,范围for,也就是底层使用的是迭代器替换。
实际上我们的迭代器遍历一遍也就类似于中序。
其实这里并不是我们给的有序然后才有序的,这里即使是无序,经过set后也是有序的。
vector<int> v{ 2,3,1,8,3,2,9,9,4,0,3,4,6,7,6,6,6,2 };set<int> se(v.begin(), v.end());for (auto e : se)cout << e << " ";cout << endl;
我们给这么一段数据,我们再看一下。
经过遍历后我们发现不仅有序还顺便去重了。
因为 set 就像我们上次的二叉搜索树一样,需要用key来比较大小然后插入,所以无法插入两个相同的值。
成员函数 insert
关于 set 的 insert 我们只看这么一个,因为只有这个最常用。
参数:参数就是 value_type 类型的一个参数,value_type 又是什么类型呢?
value_type 就是模板中的类型 T。
返回值 :返回值是一个 pair 其中 pair 的第一个参数是插入后的迭代器,或者是插入失败后的那个位置。
上面我们有一个 pair ,pair 是什么类型呢?我们下面,这里先不说。
set<int> se;se.insert(10);se.insert(3);se.insert(1);se.insert(9);se.insert(6);se.insert(8);se.insert(2);for (auto e : se)cout << e << " ";cout << endl;
这个就是我们单元素的插入,而这个也是最常用的。
iterator
set 的迭代器呢,是一个双向迭代器,并且还是 const value_type,所以set 的迭代器里面的值是不能修改的。
vector<int> v{ 2,3,1,8,3,2,9,9,4,0,3,4,6,7,6,6,6,2 };set<int> se(v.begin(), v.end());for (auto& e : se)cout << ++e << " ";cout << endl;
我们还是使用上面的一段代码,但是这里在使用范围for 的时候加了引用,我们编译一下。
所以set 的key 其实是不可修改的。
find
set 也提供了 find 就是查找传入的一个值,如果查到了就返回该位置的迭代器,否则就返回 iterator::end()
那么算法里面的查找和set提供的查找有什么不同吗?
set<int>::iterator it1 = find(se.begin(), se.end(), 1);if (it1 != se.end())cout << (*it1) << endl;auto it2 = se.find(1);if (it2 != se.end())cout << (*it2) << endl;
这里我们就用到 auto 了,可以自动推导返回值类型。
那么上面的这两个有什么区别呢?
区别:
- 算法里面的查找是一个一个查找,也就是通过迭代器一个一个遍历,时间复杂度为 O(N)
- set提供的find,的查找是搜索树的查找,时间复杂度为O(N logN)
count
set 除了提供了 find 还提供了 count,count也是和set一样的查找功能,但是返回值有差异,set返回查找到的迭代器,count返回查找到的个数。
那么对于 set 来说只能插入不同的值,要返回值个数有什么用呢?
其实这里的 count 是为了下面说的 multiset 设计,但是为了匹配一点,set 也设计了该函数。
所以这里也就不多介绍。
pair
pair 的模板参数
pair 就是一个模板的类,其中有两个值,一个是 first,另一个是second。
make_pair
make_pair 是一个模板函数,其作用就是返回饭hi一个构造的pair。
multiset使用
multiset 的模板参数
在模板参数这边,set 与 multiset 是一样的。
set 和 multiset 的区别就是set 只能插入不同值的元素,但是 multiset 可以插入相同值的元素。
所以下面的 multiset 我们就只看一下插入相同元素后遍历后的结果。
set 与 multiset 的区别
vector<int> v{ 2,3,1,8,3,2,9,9,4,0,3,4,6,7,6,6,6,2 };multiset<int> muset(v.begin(), v. end());for (auto e : muset)cout << e << " ";cout << endl;
相比set来说 multiset 即使是插入多个相同元素也是没有问题的。
count
multiset 的count 函数就是可以返回查找到元素的个数了,set 只能返回 1或者 0,但是multiset 还可以返回大于 1 的值,因为这里的 multoset 可以存入相同的值。
map使用
map 的模板参数
map 是一个 key value 的模型,一个 key 对应一个value,所以key 也同样不可以重复。
还有一个T,T就表示的是 value 的类型。
map 同样和 set 是一样的,还是需要提供一个模板参数关于比较的。
还有一个空间配置器,这里也不多介绍。
构造函数
map 的构造函数也是可以用一段区间来初始化。
map<char, int> first{ {'a', 1}, {'b', 2}, {'c', 3}, {'d', 4} };map<char, int> second(first.begin(), first.end());for (auto e : second)cout << e.first << " : " << e.second << endl;
先不要管我们下面的打印,我们先看一下能否遍历。
insert
这里 map 的插入也是返回一个 pair。
那么这里插入的 value 是什么呢?
这里的 value_type 是一个pair,所以我们插入的值也是一个pair。
这里的返回值是什么意思呢?
其中如果插入成功就返回的pair里面的 first 就是插入成功位置的迭代器,second 就是true,失败的话 first 就是一个已有的那个 key 的迭代器,second 就是false。
map<int, int> hash;pair<int, int> pair1(1, 11);hash.insert(pair1);hash.insert(pair<int, int>(2,22));hash.insert(make_pair(3, 33));
这个就是插入,这里主要是为了介绍几种插入方式,其中一个是构造一个 pair 对象,然后插入,还有一个是使用pair 的匿名对象,最后一个就是我们前面介绍的 make_pair 函数,该函数返回一个pair的对象。
iterator
这里的迭代器就是一个 value_type,并且也是双向迭代器。
find
这里的 find 返回的也是一个迭代器,而这里的迭代器又是一个 value_type类型的,所以查找到的值,里面的 first 就是key, second 就是value。
map<char, int> hash{ {'a', 1}, {'b', 2}, {'c', 3}, {'d', 4} };auto it = hash.find('a');if (it != hash.end())cout << (*it).first << ":" << (*it).second << endl;
count
map 的 count 也是和 set 是一样的,主要也是为了 multimap 设计的。
operator[]
operato[] 可以说是map 里面很重要的一个内容了,而且operator[] 同样很好用。
这里的 [] 里面传入的值是一个 key 类型的数据。
operator[] 的作用:
如果没有该元素,就插入,有的话,就返回该 key 对应的 value。
是怎么做到的?
其中 operator[] 是使用 insert 来实现的,
V& operator[](const K& key)
{pair<iterator, bool> ret = insert(key, V());return ret.first->second;
}
其实大概就是这样实现的。
multimap使用
multimap与map 的区别
这里的 multimap 与 map 实际上和 set 与 multiset 是差不多的,multimap 可以插入相同元素的值,而map 是不可以的。
其中 count 函数也就是为 multimap 设计的。
那么他们的区别是什么呢? 我觉得最大的几个区别就是上面的一个,还有一个就是multimap 是没有 operator[] 的。
因为 multimap 可以插入相同元素的值,那么operator[] 里面传入的是key, 返回的是 value,但是这里的key 不是唯一的,所以没有 operator[].