set容器基本概念
- set的特性是,所有元素都会根据元素的键值自动被排序。set的元素不像map那样可以同时拥有实值和键值,set的元素即是键值又是实值。set不允许两个元素又相同的键值。
- 我们不可以通过set的迭代器改变set元素的值,因为set元素值就是其键值,关系到set元素的排序规则。如果任意改变set元素值,会严重破坏set组织。换句话说,set的iterato是一种const_iterator
- set拥有和list某些相同的性质,当对容器中的元素进行插入操作或者是拿出操作或者删除操作的时候,操作之前所有的迭代器,在操作完成之后依然有效,被删除的那个元素的迭代器是一个例外
multiset容器的基本概念
multiset特性及用法和set完全相同,唯一的差别在于它允许键值重复,set和multiset的底层实现是红黑树,红黑树为平衡二叉树的一种
红黑树:一个结点的左边全部小于它,它的右边全部大于它
set/multiset 对象的默认构造
- setsetInt; //一个存放 int 的 set 容器。
- setsetFloat; //一个存放 float 的 set 容器。
- setsetString; //一个存放 string 的 set 容器。
- multisetmulsetInt; //一个存放 int 的 multiset 容器。
- multisetmultisetFloat; //一个存放 float 的 multiset 容器。
- multisetmultisetString; //一个存放 string 的 multiset 容器。
set 的插入与迭代器
-
set.insert(elem); //在容器中插入元素。
-
set.begin(); //返回容器中第一个数据的迭代器。
-
set.end(); //返回容器中最后一个数据之后的迭代器。
-
set.rbegin(); //返回容器中倒数第一个元素的迭代器。
-
set.rend(); //返回容器中倒数最后一个元素的后面的迭代器。
//set容器不允许插入重复的键值 void test03() {set<int>s1;pair<set<int>::iterator,bool>ret=s1.insert(10);if (ret.second == true){cout << "插入成功" << endl;}else{cout << "插入失败" << endl;}ret=s1.insert(10);if (ret.second == true){cout << "第二次插入成功" << endl;}else{cout << "第二次插入失败" << endl;}printSet(s1); }
Set 集合的元素排序
-
set<int,less> setIntA; //该容器是按升序方式排列元素。
-
set<int,greater>setIntB; //该容器是按降序方式排列元素。
-
set 相当于 set<int,less>。
-
less与 greater中的 int 可以改成其它类型,该类型主要要跟 set 容纳的数据 类型一致。
//指定set排序规则从大到小 //仿函数 //函数不能做类型,class可以做类型 class myCompare { public://重载()bool operator()(int v1, int v2){return v1 > v2;} };//set容器排序 void test04() {//set<int>s1;set<int, myCompare>s1;s1.insert(5);s1.insert(1);s1.insert(9);s1.insert(3);s1.insert(7);//从大到小排序//在插入之前就指定排序规则for (set<int, myCompare>::iterator it = s1.begin(); it != s1.end(); it++){cout << *it << " ";}cout << endl;}
set 对象的拷贝构造与赋值
-
set(constset&st); //拷贝构造函数
-
set&operator=(constset&st); //重载等号操作符 set.swap(st); //交换两个集合容器
set 的大小操作
- set.size(); //返回容器中元素的数目
- set.empty();//判断容器是否为空
set 的删除操作
- set.clear(); //清除所有元素
- set.erase(pos); //删除 pos 迭代器所指的元素,返回下一个元素的迭代器。
- set.erase(beg,end); //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
- set.erase(elem); //删除容器中值为 elem 的元素。
set 的查找操作
-
set.find(elem); //查找 elem 元素,返回指向 elem 元素的迭代器。
-
set.count(elem); //返回容器中值为 elem 的元素个数。对 set 来说,要么是 0,要 么是 1。对 multiset 来说,值可能大于 1。
-
set.lower_bound(elem); //返回第一个>=elem 元素的迭代器
-
set.upper_bound(elem); // 返回第一个>elem 元素的迭代器。
-
set.equal_range(elem); //返回容器中与 elem 相等的上下限的两个迭代器。上 限是闭区间,下限是开区间,如[beg,end)。
void test02(){set<int>s1;s1.insert(5);s1.insert(1);s1.insert(9);s1.insert(3);s1.insert(7);//对于set 没有value key就是valueset<int>::iterator pos=s1.find(2);//判断是否找到if (pos != s1.end()){cout << "找到了,值为:" << *pos << endl;}else{cout << "未找到" << endl;}//count(key)//查找键值key的元素的个数 set而言结果是0或者1int num = s1.count(2);cout << "2的个数为:" << num << endl;//lower_bound(keyElem);//返回第一个key=keyElem元素的迭代器set<int>::iterator it=s1.lower_bound(10);if (it != s1.end()){cout << "找到了,值为" << *it << endl;}else{cout << "未找到" << endl;}//upper_bound(keyElem);//返回第一个key>keyElem元素的迭代器,set<int>::iterator it2 = s1.upper_bound(3);//第一个大于3的值if (it2 != s1.end()){cout << "找到了,值为" << *it2 << endl;//5}else{cout << "未找到" << endl;}//equal_range(keyElem);//返回容器中key与keyElem相等的上下限的两个迭代器//上下限 就是lower_bound和upper_boundpair <set<int>::iterator, set<int> ::iterator> ret = s1.equal_range(3);//获取第一个值if (ret.first != s1.end()){cout << "找到equal_range中的lower_bound的值:" << *(ret.first) << endl;}else{cout << "未找到" << endl;}//获取第二个值if (ret.second != s1.end()){cout << "找到equal_range中的equal_range的值:" << *(ret.second) << endl;}else{cout << "未找到" << endl;}}
注意:
1 关联式容器
2 插入数据自动排序
3 insert插入值
4 erase参数可以传值或者迭代器
#include<iostream>using namespace std;#include<set>void printSet(set<int>&s){for (set<int>::iterator it = s.begin(); it != s.end(); it++){cout << *it << " ";}cout << endl;}void test01(){set<int>s1;//关联式容器 key进行排序,从小到大自动排序s1.insert(5);s1.insert(1);s1.insert(9);s1.insert(3);s1.insert(7);printSet(s1);if (s1.empty()){cout << "空" << endl;}else{cout << "size=" << s1.size() << endl;}s1.erase(s1.begin());//3 5 7 9printSet(s1);s1.erase(3);// 5 7 9printSet(s1);}int main(){test01();system("pause");return 0;}
pair 的使用
-
pair 译为对组,可以将两个值视为一个单元。
-
pair<T1,T2>存放的两个值的类型,可以不一样,如 T1 为 int,T2 为 float。T1,T2 也可 以是自定义类型。
-
pair.first 是 pair 里面的第一个值,是 T1 类型。
-
pair.second 是 pair 里面的第二个值,是 T2 类型。
#include<iostream>using namespace std; #include<string>void test01() {//第一种pair<string, int>p(string("Tom"), 100);//取值cout << "姓名:" << p.first << endl;cout << "年龄:" << p.second << endl;//第二种创建方式pair<string, int>p2 = make_pair("Jerry", 200);cout << "姓名:" << p.first << endl;cout << "年龄:" << p.second << endl; }int main() {test01();system("pause");return 0; }
set容器中插入自定义数据类型
//自定义数据类型class Person{public:Person(string name, int age){this->m_Name = name;this->m_Age = age;}string m_Name;int m_Age;};class myComparePerson{public:bool operator()(const Person&p1, const Person&p2){if (p1.m_Age > p2.m_Age)//降序{return true;}return false;}};void test05(){set<Person,myComparePerson>s1;Person p1("大娃", 100);Person p2("二娃", 90);Person p3("六娃", 10);Person p4("爷爷", 1000);s1.insert(p1);s1.insert(p2);s1.insert(p3);s1.insert(p4);//插入自定义数据类型,一开始必须指定排序规则//显示for (set<Person, myComparePerson>::iterator it = s1.begin(); it != s1.end(); it++){cout << "姓名:" << (*it).m_Name << "年龄" << (*it).m_Age << endl;}}int main(){//test01();//test02();//test03();//test04();test05();system("pause");return 0;}