一、set容器的基本概念
本质:set/multiset属于关联式容器,底层结构用的是二叉树实现
功能:set容器中所有的元素在插入时会自动排序,并把重复的数据给删除掉
multiset容器中的元素在插入时也会自动排序,但并没有把重复的数据给删除掉
set容器的构造与赋值:
构造函数原型:
set<T> st; //默认构造函数
set(const set &st); //拷贝构造函数
赋值函数原型:
set& operator=(const set &st); //重载等号操作符
示例:
#include "iostream"
#include <set>
using namespace std;
//创建set容器以及赋值
void PrintSet31(const set<int> &s)
{
for (set<int>::const_iterator it = s.begin(); it != s.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void SetTest31()
{
//set容器的默认构造和数据插入
set<int> s1;
s1.insert(0);
s1.insert(20);
s1.insert(30);
for (int i = 10; i > 0; i--)
{
//s1.push_back(i); 报错
//set容器插入数据只有insert一种方式
s1.insert(s1.begin(), i);
}
//s1.insert(s1.end(), 3,100); //报错
PrintSet31(s1);
//set容器的拷贝构造
set<int> s2(s1);
PrintSet31(s2);
//set容器的等号赋值操作
set<int> s3;
s3 = s1;
PrintSet31(s3);
}
int main()
{
SetTest31();
system("pause");
return 0;
}
总结:set容器插入数据的时候只能使用insert
set容器在插入数据后会自动排序
二、set容器的大小与交换
学习目标:统计set容器的大小,对两个set容器中的内容进行交换操作
函数原型:
size(); //返回set容器中的元素个数
empty(); //判断set容器是否为空
swap(st); //交换两个容器的内容
示例:
#include "iostream"
#include <set>
using namespace std;
//创建set容器以及赋值
void PrintSet32(const set<int> &s)
{
for (set<int>::const_iterator it = s.begin(); it != s.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void SetTest32()
{
//set容器的默认构造和数据插入
set<int> s1;
s1.insert(0);
s1.insert(20);
s1.insert(30);
for (int i = 10; i > 0; i--)
{
//s1.push_back(i); 报错
//set容器插入数据只有insert一种方式
s1.insert(s1.begin(), i);
}
//s1.insert(s1.end(), 3,100); //报错
//1、判断容器是否为空,不为空则输出容器的元素个数
if (!s1.empty())
{
cout << "s1容器不为空:" << endl;
PrintSet32(s1);
cout << "s1容器的大小为:" << s1.size() << endl;
}
else
{
cout << "s1容器为空!!!!!!!!!!!!!:" << endl;
}
set<int> s2;
s2.insert(100);
s2.insert(200);
s2.insert(300);
s2.insert(400);
s2.insert(500);
cout << "未进行交换前:" << endl;
PrintSet32(s1);
PrintSet32(s2);
cout<< "在进行交换后:" << endl;
s1.swap(s2);
PrintSet32(s1);
PrintSet32(s2);
}
int main()
{
SetTest32();
system("pause");
return 0;
}
三、set容器的插入与删除
学习目标:对set容器进行数据的插入与删除操作
函数原型:
insert(elem); //在容器中插入元素
clear(); //清除所有元素
erase(pos); //删除pos迭代器所指向的元素,返回下一个元素的迭代器
erase(beg,end); //删除[beg,end)区间的所有迭代器所指向的所有元素,返回下一个元素的迭代器
erase(elem); //删除容器中值为elem的元素
示例:
#include "iostream"
#include <set>
using namespace std;
//创建set容器以及赋值
void PrintSet33(const set<int> &s)
{
for (set<int>::const_iterator it = s.begin(); it != s.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void SetTest33()
{
//set容器的默认构造和数据插入
set<int> s1;
s1.insert(0);
s1.insert(20);
s1.insert(30);
for (int i = 10; i > 0; i--)
{
//s1.push_back(i); 报错
//set容器插入数据只有insert一种方式
s1.insert(s1.begin(), i);
}
//s1.insert(s1.end(), 3,100); //报错
PrintSet33(s1);
//2.erase()
cout << "删除第一个元素:" << endl;
s1.erase(s1.begin());
PrintSet33(s1);
cout << "删除值为1的元素:" << endl;
s1.erase(1);
PrintSet33(s1);
set<int>::iterator itb = s1.begin();
itb++;
set<int>::iterator ite = s1.end();
ite--;
ite--;
s1.erase(itb, ite);
PrintSet33(s1);
//cout << "随机访问第一个元素:" << s1[0] << endl; 不支持随机迭代器
//3.清除clear()
s1.clear();
PrintSet33(s1);
}
int main()
{
SetTest33();
system("pause");
return 0;
}
四、set容器的查找与统计
学习目标:对set容器中的数据进行查找以及统计数据
函数原型:
find(key); //查找key是否存在,若存在,返回该元素的迭代器,若不存在,返回set.end();
count(key); //统计key元素的个数
示例:
#include "iostream"
#include <set>
using namespace std;
//创建set容器以及赋值
void PrintSet34(const set<int> &s)
{
for (set<int>::const_iterator it = s.begin(); it != s.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void SetTest34()
{
//set容器的默认构造和数据插入
set<int> s1;
s1.insert(0);
s1.insert(20);
s1.insert(30);
s1.insert(30);
s1.insert(30);
for (int i = 10; i > 0; i--)
{
//s1.push_back(i); 报错
//set容器插入数据只有insert一种方式
s1.insert(s1.begin(), i);
}
//s1.insert(s1.end(), 3,100); //报错
PrintSet34(s1);
//1、查找
set<int>::iterator pos = s1.find(30);
if (pos != s1.end())
{
cout << "找到元素:" << *pos << endl;
}
else
{
cout << "没有找到元素" << endl;
}
//2、统计 对与set容器而言,统计的结果要么0,要么是1.
int num = s1.count(30);
cout << "找到值为30 的元素个数是:" << num << endl; //1
}
int main()
{
SetTest34();
system("pause");
return 0;
}
总结:查找——find (返回的是迭代器)
统计——count(对于set容器,结果为0或1)
五、set与multiset的区别
学习目标:掌握set与multiset的区别
区别:set不可以插入重复数据,而multiset可以
set插入数据的同时会返回插入结果,表示插入是否成功
multiset不会检测数据,可以插入重复的数据
示例:
#include "iostream"
#include <set>
//#include <multiset>
using namespace std;
void pairResult(pair<set<int>::iterator, bool> ret)
{
if (ret.second)
{
cout << "插入数据成功!" << endl;
}
else
{
cout << "插入数据失败!" << endl;
}
}
void SetTest35()
{
set<int> s1;
cout << "第一次插入数据:" << endl;
pair<set<int>::iterator, bool> ret=s1.insert(10); //返回迭代器和一个bool
pairResult(ret);
cout << "第二次插入数据:" << endl;
ret = s1.insert(10);
pairResult(ret);
cout << "multiset插入重复性的数据:" << endl;
multiset<int> ms; //允许插入重复值
ms.insert(10);
ms.insert(10);
ms.insert(10);
ms.insert(10);
ms.insert(10);
for (multiset<int>::iterator it = ms.begin(); it != ms.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
int main()
{
SetTest35();
system("pause");
return 0;
}
总结:如果不允许插入相同的数据,可以使用set容器
如果允许插入相同的数据,请使用multiset容器
六、pair使用——pair对组的创建
功能描述:成对出现的数据,利用对组可以返回两个数据
两种创建的方式:
pair<type,type> p(value1,value2);
pair<type,type> p=make_pair(value1,value2);
示例:
#include "iostream"
#include <set>
#include <string>
using namespace std;
void SetTest36()
{
//第一种方式
pair<string, int> p1("小猫",3);
cout << "姓名:" << p1.first << " 年龄:" << p1.second << endl;
//第二种方式
pair<string, int> p2 = make_pair("小狗", 11);
cout << "姓名:" << p2.first << " 年龄:" << p2.second << endl;
}
int main()
{
SetTest36();
system("pause");
return 0;
}
七、set容器内置数据类型指定的排序规则
学习目标:掌握set容器的默认排序规则:从小到大。掌握如何利用仿函数改变排序规则
技术要点:利用仿函数,改变排序规则
示例:
#include "iostream"
#include <set>
#include <string>
using namespace std;
void PrintSet37(const set<int> &s)
{
for (set<int>::const_iterator it = s.begin(); it != s.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
//仿函数是一个类
class setCompare
{
public:
bool operator()(int v1,int v2) {
return v1 > v2;
}
};
void SetTest37()
{
set<int> s1;
s1.insert(50);
s1.insert(20);
s1.insert(30);
s1.insert(10);
s1.insert(40);
cout << "默认排序规则:" << endl;
PrintSet37(s1);
//指定排序规则:从大到小
//s1.sort(setCompare); set容器没有sort成员函数
set<int, setCompare> s2;
s2.insert(10);
s2.insert(20);
s2.insert(30);
s2.insert(40);
s2.insert(50);
for (set<int, setCompare>::iterator it = s2.begin(); it != s2.end(); it++)
{
cout << *it << " ";
}
}
int main()
{
SetTest37();
system("pause");
return 0;
总结:仿函数是重载某个类下的 bool operator()(参数1,参数2){}
把仿函数传入set容器,实现改变规则。set<int,仿函数所在的类类名> st;
八、set容器自定义数据类型排序
#include "iostream"
#include <set>
#include <string>
using namespace std;
class setPerson
{
public:
setPerson(string name, int age)
{
this->m_Name = name;
this->m_Age = age;
}
string m_Name;
int m_Age;
};
//创建仿函数,指定排序规则
class PersonCompare {
public:
bool operator()(const setPerson &p1,const setPerson &p2)
{
return p1.m_Age < p2.m_Age;
}
};
void SetTest38()
{
//1、创建setPerson对象
setPerson p1("张三",21);
setPerson p2("李四", 12);
setPerson p3("王五", 25);
setPerson p4("飞流", 8);
setPerson p5("二七", 1);
setPerson p6("三八", 38);
//创建set容器,把自定义的setPerson数据类型放入到set容器中
set<setPerson, PersonCompare> sp;
sp.insert(p1);
sp.insert(p2);
sp.insert(p3);
sp.insert(p4);
sp.insert(p5);
sp.insert(p6);
//循环遍历,输出。在未指定排序规则时,set容器会报错
for (set<setPerson, PersonCompare>::iterator it = sp.begin(); it != sp.end(); it++)
{
cout << "姓名:" << it->m_Name << " 年龄:" << it->m_Age << endl;
}
}
int main38()
{
SetTest38();
system("pause");
return 0;
}
总结:对于自定义数据类型,set必须指定排序规则,才可以插入数据