set容器
一、set容器
一、set容器的基本概念
- 所有元素都会在插入set容器时自动排序
- set/multiset属于关联式容器,底层结构是二叉树
- set容器不允许存在重复元素
- multiset允许存在重复元素
二、set容器的构造与赋值
#include<iostream>
#include<set>
using namespace std;
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;
s1.insert(10);
s1.insert(20);
s1.insert(30);
s1.insert(40);
printSet(s1);
set<int>s2(s1);
printSet(s2);
set<int>s3;
s3 = s2;
printSet(s3);
}
自行设置一个打印函数。set容器用insert插入数据,无需指定位置,按照自身顺序插入数据。拷贝构造和=号赋值可以使用。
三、set容器的大小与交换
void test02()
{
set<int>s1;
s1.insert(10);
s1.insert(20);
s1.insert(30);
s1.insert(40);
printSet(s1);
if (s1.empty())
cout << "s1为空" << endl;
else
cout << "s1不为空,元素个数为:" <<s1.size()<< endl;
set<int>s2;
s2.insert(1);
s2.insert(3);
s2.insert(5);
s2.insert(7);
cout << "交换前" << endl;
printSet(s1);
printSet(s2);
cout << "交换后" << endl;
s1.swap(s2);
printSet(s1);
printSet(s2);
}
这些容器基本都是这么几个函数,知道怎么用就行
四、set容器的插入与删除
void test03()
{
set<int>s1;
s1.insert(10);
s1.insert(20);
s1.insert(30);
s1.insert(40);
printSet(s1);
s1.erase(s1.begin());
printSet(s1);
s1.erase(30);
printSet(s1);
s1.clear();
printSet(s1);
}
这里的erase有传值删除的重载版本
五、set容器的查找与统计
void test04()
{
set<int>s1;
s1.insert(10);
s1.insert(20);
s1.insert(30);
s1.insert(40);
//无效
s1.insert(30);
s1.insert(30);
auto pos=s1.find(30);
if (pos != s1.end())
cout << "找到了" << *pos << endl;
else
cout << "没找到" << endl;
int num = s1.count(30);
cout << "num=" << num << endl;
}
find的返回值类型是迭代器类型
set容器不允许有重复数据,因此count计数的结果要么是0,要么是一
六、set和multiset的区别
void test05()
{
set<int>s;
pair<set<int>::iterator, bool>ret = s.insert(10);
if (ret.second)
cout << "第一次插入成功" << endl;
else
cout << "第一次插入失败" << endl;
ret = s.insert(10);
if (ret.second)
cout << "第二次插入成功" << endl;
else
cout << "第二次插入失败" << endl;
multiset<int>ms;
ms.insert(10);
ms.insert(10);
ms.insert(10);
for (auto it : ms)
cout << it << " ";
cout << endl;
}
二者最主要的区别在于是否能插入重复元素
multiset的使用无需引入新的头文件,上述案例中,pair是对组。下面会讲
模板中第一个类型是迭代器,第二个是bool类型,ret接收后,ret.second表示第二个参数返回值,及bool类型。可以看到set第二次插入重复数据就失败了,而multiset可以多次插入重复数据。
七、set容器排序
set容器默认从小到大排序,利用仿函数可以改变排序规则
class cmp
{
public:
bool operator()(int v1, int v2)
{
return v1 > v2;
}
};
void test06()
{
set<int>s1;
s1.insert(10);
s1.insert(30);
s1.insert(50);
s1.insert(40);
s1.insert(20);
printSet(s1);
set<int,cmp>s2;
s2.insert(10);
s2.insert(30);
s2.insert(50);
s2.insert(40);
s2.insert(20);
for (set<int, cmp>::iterator it = s2.begin(); it != s2.end(); it++)
cout << *it << " ";
cout << endl;
}
可以看到默认存储为升序,降序需要设置一个仿函数
对于自定义数据类型的存储必须设置仿函数,否则set不知道如何存储
#include<string>
class Person
{
public:
Person(string name, int age)
{
this->m_age = age;
this->m_name = name;
}
string m_name;
int m_age;
};
class Compare
{
public:
bool operator()(const Person&p1, const Person&p2)
{
return p1.m_age > p2.m_age;
}
};
void test07()
{
set<Person,Compare>s;
Person p[5] =
{
{"关羽",28},
{"张飞",25},
{"赵云",24},
{"马超",23},
{"黄忠",30}
};
for (int i = 0; i <5; i++)
s.insert(p[i]);
for (set<Person,Compare>::iterator it=s.begin();it!=s.end();it++)
cout << "姓名:" << it->m_name << "年龄:" << it->m_age << endl;
}
这里需要注意,只要姓名和年龄有元素重复,set容器第二次存储都会失败,当作重复存储
二、对组pair
成对出现的数据,利用对组我们可以返回两个数据
#include<iostream>
#include<string>
using namespace std;
int main()
{
pair<string, int>p("Tom", 20);
cout << "姓名:" << p.first << " 年龄" << p.second << endl;
pair<string, int>q("Jerry", 20);
cout << "姓名:" << q.first << " 年龄" << q.second << endl;
return 0;
}
像这样就可以存储多个数据,像简化的结构体,不过只能存两个,从名字对组也能看出