0.首先说明一下容器的类型
1.序列式容器:数据间进行swap是不会剧烈破坏容器结构的。如:vector,list等
2.关联式容器:数据间进行swap不会剧烈破坏容器结构的。如:set,map等
1.set容器的初始化
1.模板的参数
T(应该是K)是容器存储数据的类型,compare是set的比较方式核心是中序遍历是升序还是降序,默认是升序,Alloc是内存池,暂时不管。
2.迭代器的类型是双向迭代器

set中的迭代器是不允许修改数据的。(不是const_iterator,但iterator也是不给修改的,给修改整棵树的结构就出错了)

3.比较的方式
less<K> 树的结构是左边大右边小。
greate<K> 树的结构是左边大右边小。
只用less实现大小比较的方式:
cpp
//小于比较
less(cur->_key,key);
//大于比较
less(key,cur->_key);
//二者的顺序修改一下即可
4.初始化的方式
cpp
int main()
{
//用的initailize_list参数的构造函数
set<int> s1({ 1, 2, 3, 4, 5, 5 });
//此处的右边并不是initailize_list类型,但符合其构造函数的参数类型
//因此右边就用构造函数来生成临时对象,然后调用拷贝构造函数给s2赋值
//只是编译器优化成了直接调用成了构造函数
set<int> s2 = { 1,3,4,5,6 };
//这里就是调用构造函数来生成临时对象,然后调用拷贝构造函数给s2赋值
s2 = { 2,4,5,5 };
return 0;
}
2.set的成员函数
1.erase和count和find成员函数

(2)中的size_type返回的是删除的元素次数
(1)和(3)处的所有迭代器在erase后都会失效。
count返回val的出现次数

能用于间接查找该数是否存在:
cpp
set<int> s1({1, 3, 5});
int a = 3, b = 4;
//1即是有,0即是无
cout << s1.count(a) << endl;
cout << s1.count(4) << endl;
find,返回该val所在的迭代器,没有找到返回end处的迭代器。

(在multipleset中的find是用中序遍历查找的,必须是返回中序逻辑中找的第一个,中途遇到过也是无视的,选中序第一个的原因就是可以不断地++来找到其他的相同的值。)
2.lower_bound和upper_bound

lower_bound:返回大于等于val的迭代器区间
upper_bound:返回大于val的迭代器区间
例:查找一个区间的值
cpp
int main()
{
set<int> s1;
for (int a = 1; a <= 10; a++)
{
s1.insert(a * 10);
}
for (auto& e : s1)
{
cout << e << ' ';
}
cout << endl;
//找[30,50]区间
auto e1 = s1.lower_bound(30);
//e2是 >= 51的区间
auto e2 = s1.upper_bound(50);
s1.erase(e1, e2);
for (auto& e : s1)
{
cout << e << ' ';
}
cout << endl;
return 0;
}
查找[25,35]也是直接修改即可:
cpp
auto e1 = s1.lower_bound(25);
auto e2 = s1.upper_bound(55);
可以发现upper_bound反而有助于闭区间的寻找。开去间反过来用即可。
lower_bound和upper_bound的本质还是logN查找,只是终止条件有所不同了。
题1:找两数组的交集
解法:用双指针分别指向一个数组,it1,it2。
二者相等就都++,不同就让小的++。但前提是二者都有序,因此二者都要放进set中(顺便去重)。
题2:带环链表
解法:设计一个set不断插入结点的地址直到遇到相同结点或遇到nullptr。

3.map的使用
首先对pair这个c++自带的类类型介绍一下:
cpp
template<class T1,class T2>
struct pair
{
T1 first;
T2 second;
//和几个成员函数..
}
在map中被typedef pair<const K,class V> value_type了。
用途就是将key和value统筹成一个类类型成员。
使用:(注意,map不可以用pair(同模板参数)变量来初始化,但可以用insert)
make_pair:c++库中用于返回生成一个pair类型的(核心用途就是用于简化代码)
cpp
int main()
{
pair<int,int> a = pair<int, int>(1, 2);
map<int, int> m;
m.insert(pair<int, int>(8, 2));
m.insert(make_pair(4, 9));
return 0;
}
也支持多类型转换和initailize_list的的构造
cpp
//调用c++11后支持的多参构造
map<int, int>s({1,2});
//调用initialize_list的构造函数
map<int, int> s1 = { {1,2},{4,5},{8,9} };
获取数据:
cpp
map<int, int> s1 = { {1,2},{4,5},{8,9} };
auto a = s1.begin();
//map的迭代器也是经过重载的,返回的是pair成员变量
cout << (*a).first << (*a).second << endl;
//和list一样,当调用的成员是类类型时都有->重载
//照样返回的是地址,照样省略了operator->调用
cout << a->first << a->second << endl;
map<int, int> s3;
s3.insert(1, 2);
//不会修改,查找的根据只与key有关
s3.insert(1, 1);
cout << (*s3.begin()).first << (*s3.begin()).second << endl;
a->first++;//不允许修改key
a->second;//允许修改value;