文章目录
1 set基本概念
set / multiset
属于关联式容器,底层结构采用红黑树实现。
特点:插入无序元素时,会自动完成排序。(输入无序序列,输出有序)
set和multiset的区别:
set
:不允许容器中存在重复元素;
multiset
:允许容器中存在重复元素。
2 set构造函数和赋值【operator=】
作用:创建set容器及赋值。
注:使用set容器时,需包含头文件
#include <set>
。
构造函数:
①set<T> st;
:默认无参构造函数,采用类模板实现。
②set(const set &st);
:拷贝构造函数,使用已有set对象初始化新的对象。
赋值操作:
set& operator=(const set &st);
:重载赋值运算符,使用目标set容器,对当前set容器赋值。
示例:set构造函数和赋值
#include <iostream>
using namespace std;
#include <set>
//函数模板:遍历set容器的通用函数
template<typename T>
void printSet(const set<T>& s) { //形参使用const,避免被修改
//形参使用const后,遍历时需使用只读迭代器const_iterator
//使用typename关键字,防止编译器报错:C2760(语法错误,意外标记“标识符”)
for (typename set<T>::const_iterator it = s.begin(); it != s.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
int main() {
//1.默认无参构造
set<int> s;
//插入元素
s.insert(9);
s.insert(1);
s.insert(7);
s.insert(3);
s.insert(5);
//自动排序
printSet<int>(s); //1 3 5 7 9
//2.拷贝构造
set<int> s1(s);
printSet<int>(s1); //1 3 5 7 9
//3.赋值操作
set<int> s2;
s2 = s1;
printSet<int>(s2); //1 3 5 7 9
return 0;
}
3 set大小【size()】和交换【swap()】
大小操作:
size();
:获取容器的大小,即元素个数。
empty();
:判断容器是否为空。
注:set集合不允许出现重复元素,故不支持
resize()
操作,避免指定长度变大时,填充默认值或指定值时插入重复元素。
交换操作:
swap(st);
:将目标set容器st
与自身的元素互换。
示例:
#include <iostream>
using namespace std;
#include <set>
//函数模板:遍历set容器的通用函数
template<typename T>
void printSet(const set<T>& s) { //形参使用const,避免被修改
//形参使用const后,遍历时需使用只读迭代器const_iterator
//使用typename关键字,防止编译器报错:C2760(语法错误,意外标记“标识符”)
for (typename set<T>::const_iterator it = s.begin(); it != s.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
int main() {
//默认无参构造
set<int> s1;
//插入元素
s1.insert(9);
s1.insert(1);
s1.insert(7);
s1.insert(3);
s1.insert(5);
//empty() 判断是否为空
cout << (s1.empty() ? "空" : "非空") << endl; //非空
//size() 大小
cout << s1.size() << endl; //5
/* 交换操作 */
set<int> s2;
s2.insert(4);
s2.insert(8);
s2.insert(6);
s2.insert(2);
cout << "交换前:" << endl;
printSet(s1); //1 3 5 7 9
printSet(s2); //2 4 6 8
//swap() 交换操作
s1.swap(s2);
cout << "交换后:" << endl;
printSet(s1); //2 4 6 8
printSet(s2); //1 3 5 7 9
return 0;
}
4 set插入【insert()】和删除【erase()、clear()】
(1)插入元素:使用成员函数insert(..)
向set容器插入元素。
函数原型:
insert(elem);
:向set容器插入元素elem
(2)删除元素:使用成员函数erase(..)
、clear(..)
删除set容器中的元素。
函数原型:
①erase(const_iterator pos);
:删除迭代器指向位置的元素。
②erase(const_iterator start, const_iterator end);
:删除迭代器指向位置[start, end)
区间的所有元素。
③erase(elem);
:删除容器中值为elem
元素。
④clear();
:清空容器中的所有元素。
注:清空容器的所有元素,
s.clear();
等价于s.erase(s.begin(), s.end());
。
示例:set容器插入和删除元素
#include <iostream>
using namespace std;
#include <set>
//函数模板:遍历set容器的通用函数
template<typename T>
void printSet(const set<T>& s) { //形参使用const,避免被修改
//形参使用const后,遍历时需使用只读迭代器const_iterator
//使用typename关键字,防止编译器报错:C2760(语法错误,意外标记“标识符”)
for (typename set<T>::const_iterator it = s.begin(); it != s.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
int main() {
//默认无参构造
set<int> s;
//插入元素
s.insert(9);
s.insert(1);
s.insert(7);
s.insert(3);
s.insert(5);
printSet(s); //1 3 5 7 9
//删除单个元素
s.erase(s.begin());
printSet(s); //3 5 7 9
//删除指定值
s.erase(5);
printSet(s); //3 7 9
//清空元素
s.erase(s.begin(), s.end());
//s.clear();
printSet(s); //(空)
return 0;
}
5 set查找【find()】和统计【count()】
查找元素:
find(key);
:查找目标值key
是否存在。若存在,则返回该值对应元素的迭代器指向位置;若不存在,则返回结束迭代器 s.end()。
注:成员函数
find(key);
返回值为迭代器类型。
//判断set容器是否存在某元素
int val = 5;
//查找元素,返回迭代器类型
set<int>::iterator pos = s.find(val);
//判断元素是否存在
if(pos != s.end()){
cout << "查找到目标值:" << *pos << endl;
}
统计元素个数:
count(key);
:统计目标值key
的元素个数。
①set容器
:元素不可重复,返回结果为0
或1
。
②multiset容器
:元素可重复,返回结果为0
、1
或n
。
示例:set查找元素和统计元素个数
#include <iostream>
using namespace std;
#include <set>
//查找元素
void func1() {
set<int> s;
//插入元素
s.insert(9);
s.insert(1);
s.insert(7);
s.insert(3);
s.insert(5);
int key = 5;
//find():查找元素,返回迭代器类型
set<int>::iterator pos = s.find(key);
//判断元素是否存在
if (pos != s.end()) {
cout << "查找到目标值:" << *pos << endl;
}else{
cout << "未找到目标值:" << endl;
}
}
//统计元素个数-set容器
void func2() {
set<int> s;
//插入元素
s.insert(9);
s.insert(1);
s.insert(7);
s.insert(3);
s.insert(5);
s.insert(5);
s.insert(5);
//set容器:元素不可重复,返回结果为0或1。
cout << s.count(5) << endl; //1
}
//统计元素个数-multiset容器
void func3() {
multiset<int> s;
//插入元素
s.insert(9);
s.insert(1);
s.insert(7);
s.insert(3);
s.insert(5);
s.insert(5);
s.insert(5);
//multiset容器:元素可重复,返回结果为0、1或n。
cout << s.count(5) << endl; //3
}
int main() {
//func1();
//func2();
func3();
return 0;
}
6 set和multiset区别
set和multiset的区别:
set
:不可插入重复数据。
pair<iterator, bool> insert(value_type&& _Val);
set容器insert(elem)
函数返回值类型为pair对组pair<iterator, bool>
,会返回插入操作的结果,即不可以插入重复元素。
multiset
:可插入重复数据。
iterator insert(value_type&& _Val);
multiset容器insert(elem)
函数返回值类型为iterator
,不会返回插入操作的结果,即可以插入重复元素。
示例:
#include <iostream>
using namespace std;
#include <set>
//set插入数据
void func1() {
set<int> s;
//pair<iterator, bool> insert(value_type && _Val);
//set容器的insert()元素返回 对组类型<迭代器类型, 布尔类型>
pair<set<int>::iterator, bool> pair1 = s.insert(1); //第1次插入元素1
if (pair1.second) { //第2个参数:布尔类型
cout << "数据1插入成功.." << endl;
}
else {
cout << "数据1插入失败.." << endl;
}
pair<set<int>::iterator, bool> pair2 = s.insert(1); //第2次插入元素1
if (pair2.second) { //第2个参数:布尔类型
cout << "数据1再次插入成功.." << endl;
}
else {
cout << "数据1再次插入失败.." << endl;
}
//数据1插入成功..
//数据1再次插入失败..
}
//multiset插入数据
void func2() {
multiset<int> ms;
//iterator insert(value_type && _Val);
//multiset容器的insert()元素返回 迭代器类型
set<int>::iterator it1 = ms.insert(1); //第1次插入元素1
set<int>::iterator it2 = ms.insert(1); //第2次插入元素1
for (typename set<int>::const_iterator it = ms.begin(); it != ms.end(); it++) {
cout << *it << " "; //1 1(两次插入元素1均成功)
}
}
void main() {
//func1();
func2();
}
7 pair对组创建
对组:成对出现的数据。使用对组可返回两个数据。
对组的创建方式:
(1)有参构造函数:pair<type1, type2> p(value1, value2);
(2)make_pair()函数:pair<type1, type2> p = make_pair(value1, value2);
对组元素的访问方式:
成员属性first
:返回对组第1个元素的值;
成员属性second
:返回对组第2个元素的值。
示例:对组的使用
#include <iostream>
using namespace std;
void main() {
//创建对组-有参构造函数
pair<string, int> p1("Tom", 16);
cout << p1.first << endl; //Tom
cout << p1.second << endl; //16
//创建对组-make_pair函数
pair<string, int> p2 = make_pair("Jerry", 18);
cout << p2.first << endl; //Jerry
cout << p2.second << endl; //18
}
8 set容器排序【仿函数operator()】
set容器默认升序排序,利用仿函数,通过重载小括号operator()
在插入元素之前指定排序规则,并在创建set容器对象时,向set容器的类模板参数列表传入指定排序规则。
/* 定义自定义排序规则的仿函数的类 */
//使用类模板增强通用性
template<class T>
class MyCompare {
public:
/* 重载仿函数() */
//第1个小括号:重载小括号运算符
//第2个小括号:operator()函数的形参列表的小括号
//必须使用const修饰operator()函数
//否则编译器报错:const MyCompare的表达式会丢失 const-volatile 限定符
bool operator()(T val1, T val2) const {
return val1 > val2; //降序排序
//return val1 < val2; //升序排序
}
};
/* 创建set容器对象时,向set容器的类模板参数列表传入指定排序规则MyCompare类型 */
//类模板参数列表需传入类型,使用包含仿函数的MyCompare类型
set<double, MyCompare<double>> s;
注:使用set容器对自定义数据类型排序时,必须指定排序规则。
示例1:set容器对内置数据类型排序
#include <iostream>
using namespace std;
#include <set>
/* 定义自定义排序规则的仿函数的类 */
//使用类模板增强通用性
template<class T>
class MyCompare {
public:
/* 重载仿函数() */
//第1个小括号:重载小括号运算符
//第2个小括号:operator()函数的形参列表的小括号
//必须使用const修饰operator()函数
//否则编译器报错:const MyCompare的表达式会丢失 const-volatile 限定符
bool operator()(T val1, T val2) const {
return val1 > val2; //降序排序
//return val1 < val2; //升序排序
}
};
int main() {
//创建set容器对象时,向set容器的类模板参数列表传入指定排序规则MyCompare类型
//类模板参数列表需传入类型,使用包含仿函数的MyCompare类型
set<double, MyCompare<double>> s;
//插入元素
s.insert(6.6);
s.insert(3.3);
s.insert(9.9);
s.insert(1.1);
s.insert(7.7);
//遍历set容器
for (set<double, MyCompare<double>>::iterator it = s.begin(); it != s.end(); it++) {
cout << *it << " "; //9.9 7.7 6.6 3.3 1.1
}
cout << endl;
return 0;
}
示例2:set容器对自定义数据类型排序
#include <iostream>
using namespace std;
#include <set>
class Student {
public:
string name;
int score;
Student(string name, int score) {
this->name = name;
this->score = score;
}
};
/* 定义自定义排序规则的仿函数的类 */
class MyCompare {
public:
/* 重载仿函数() */
//必须使用const修饰operator()函数
bool operator()(Student s1, Student s2) const {
return s1.score > s2.score; //升序排序
//return s1.score < s2.score; //降序排序
}
};
int main() {
//创建set容器对象时,向set容器的类模板参数列表传入指定排序规则MyCompare类型
set<Student, MyCompare> s;
//插入元素
Student s1("Jack", 80);
Student s2("Tom", 100);
Student s3("Jerry", 60);
Student s4("Lucy", 90);
s.insert(s1);
s.insert(s2);
s.insert(s3);
s.insert(s4);
//遍历set容器
for (set<Student, MyCompare>::iterator it = s.begin(); it != s.end(); it++) {
cout << "姓名:" << (*it).name << ",成绩:" << it->score << endl;
}
//姓名:Tom,成绩:100
//姓名:Lucy,成绩:90
//姓名:Jack,成绩:80
//姓名:Jerry,成绩:60
return 0;
}