关联容器 :底层都是用红黑树(二叉排序树、平衡树)实现,前序遍历(左中右)排列有序,即根节点的左子树最小,右子树最大
红黑树插入方式:给红黑树插入节点1、2、3、4时。
先开辟一个节点,插入1,左子树和右子树为空;再构造2的节点(即再开辟一个节点,插入2)(如图1所示);要以前序遍历排列有序,将2和1进行比较,2大,进行树调整(如图2所示);再构造3的节点,不进行树调整,直接插入进去(如图3所示);再构造4的节点,将4和2进行比较,4大,进行树调整(如图4所示),3做根节点,2做根节点的左子树,1做2的左子树,4做3的右子树。现在以前序遍历有序。底层为红黑树的关联容器问题:再插入数据时,不断调整所有节点的位置,导致所有迭代器失效。
![](https://i-blog.csdnimg.cn/blog_migrate/bf17eed604d603003fd12361a3a08592.png)
![](https://i-blog.csdnimg.cn/blog_migrate/36b0a95411a445360da9d30d7d4ff6a6.png)
![](https://i-blog.csdnimg.cn/blog_migrate/7461064bc9c0041efd278365aeb7f830.png)
![](https://i-blog.csdnimg.cn/blog_migrate/7ba13d6a477fcd580df7f5fb30cb68a5.png)
set 单重集合 multiset 多重集合
set 集合中的元素一定要能进行大小的比较
#include <iostream>
#include <set>
#include <iterator>
#include <algorithm>
using namespace std;
template<typename Container>
void show(Container& con)
{
copy(con.begin(),con.end(),ostream_iterator<typename Container::value_type>(cout," "));
cout << endl;
}
int main()
{
set<int> st1;//set的构造方式一:不用传入参数(默认的构造函数)
int arr[] = {12,4,5,34,78,93,23};
int len = sizeof(arr) / sizeof(arr[0]);
set<int> st2(arr,arr+len);//set的构造方式二:通过数组构造集合对象
show(st2);//打印直接有序 底层是二叉排序树
//st1 是空集合 里面没有push方法 为什么? 针对树型结构给里面前插或后插或按位置插入没有意义,都会排序调整整个节点
st1.insert(10);// set 插入数据
st1.insert(10);// set 插入两个或以上相同数据时,实际输出只有一个 原因:set 是单重集合,不允许键重复
show(st1);
multiset<int> mst1;// multiset 多重集合,允许键重复
mst1.insert(20);
mst1.insert(20);
show(mst1);
st2.erase(93);// set 删除数据 有按值删、按迭代器区间删、按位置删三种重载
st2.erase(st2.begin());
st2.clear();// set 清空所有元素
show(st2);
//查找里面的元素,并给这个元素的位置插入一个数据
set<int>::iterator sit = find(st2.begin(),st2.end(),12);
if(sit == st2.end())
{
cout << "不存在" << endl;
}
if(sit != st2.end())
{
cout << "存在,插入数据" << endl;
st2.insert(sit,444);//实际并没有在12的位置插入,插入后根据大小调整重新找位置
}
show(st2);
return 0;
}
map 单重映射 multimap 多重映射
map 键值对的单重映射 只能一个键对应一个值,不允许值重复
#include <iostream>
#include <map>
#include <iterator> //迭代器头文件
#include <algorithm> //泛型算法头文件 本文件具体是 sort
using namespace std;
int main()
{
map<int,int> mp1;//map 的构造方式一:不用传入参数(所有的容器都支持默认的构造函数) 生成 mp1 映射对象
//<int,int> 不仅要给出键的类型,还要给出值的类型
//int arr[] ={1,2,4,6,26,76,89,30};
//int len = sizeof(arr) / sizeof(arr[0]);
//map<int,int> mp2(arr,arr + len); //无法通过普通的迭代区间来构造 map 的对象
// map 的插入一:按数据类型插入
cout << typeid(map<int,int>::value_type).name() << endl;//打印出 map 里面的具体类型
//struct std::pair<int const ,int> map 里面是个 pair 的结构体,键类型为 int const, 值类型为 int
typedef struct std::pair<int const ,int> PAIR;// 将 pair 的这个结构体重定义为 PAIR
PAIR pair1(1,111);//用 PAIR 结构体生成变量 pair1,在里面传入数据 键指,数值
//相当于把 map 里面的一个节点构造好了,再把此节点插入 map 中
mp1.insert(pair1);// 通过调用 mp1 的 insert,将 pair1 插入进去
// map 的插入二:按值类型插入
typedef map<int,int>::value_type VALUETYPE;//将 值类型重定义
VALUETYPE val1(2,222);//用值类型生成值的对象 val1 在里面传入数据 键指,数值
mp1.insert(val1);
// map 的插入三:通过赋值插入
mp1[3] = 333;
map<int,int>::iterator it = mp1.begin();
for(it;it != mp1.end();it++)
{
cout << it->first << " ";//first表键 second表值
cout << it->second << endl;
}
cout << endl;
return 0;
}