set/multiset容器
set/multiset容器
头文件:#include <set>
1. set 基本概念
- 所有元素都会在插入时自动被排序
- set/multiset属于关联式容器,底层结构是用二叉树实现。
set和multiset区别:
- set不允许容器中有重复的元素
- multiset允许容器中有重复的元素
2. set 构造和赋值
构造:
set<T> st;
//默认构造函数:set(const set &st);
//拷贝构造函数
赋值:
set& operator=(const set &st);
//重载等号操作符
示例:
set<int> s1;
s1.insert(10);
//拷贝构造
set<int>s2(s1);
printSet(s2);
//赋值
set<int>s3;
s3 = s2; // 输出的值和s1一致
3. set 插入和删除
函数原型:
insert(elem);
//在容器中插入元素。clear();
//清除所有元素erase(pos);
//删除 pos 迭代器所指的元素,返回下一个元素的迭代器。erase(beg, end);
//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。erase(elem);
//删除容器中值为 elem 的元素。
示例:
for (set<int>::iterator it = s.begin(); it != s.end(); it++)
{
cout << *it << " ";
}
set<int> s1;
//插入
s1.insert(10);
//删除
s1.erase(s1.begin());
// s1.erase(s1.begin() + 1); // 这是错误的
// 使用迭代器
set<int>::iteration it = s1.begin();
s1.erase(++it);
s1.erase(s1.begin(), s1.end());
s1.erase(10); // 如不存在,不删除
//清空
s1.clear();
4. set 大小和交换
函数原型:
size();
//返回容器中元素的数目empty();
//判断容器是否为空swap(st);
//交换两个集合容器
示例:
s1.swap(s2);
s1.size();
s1.empty();
5. set 查找和统计
函数原型:
find(key);
//查找 key 是否存在,若存在,返回该键的元素的迭代器;若不存在,返回 set.end();count(key);
//统计key的元素个数
示例:
s1.count(30);
if(s1.find(30)!=s1.end())
cout << "找到";
// 同理,if(s1.find(30) != s1.end() - 1)是错误的
// 但是可以使用迭代器
总结:
- 查找 --- find (返回的是迭代器)
- 统计 --- count (对于set,结果为0或者1)
6. set 和 multiset 区别
区别:
- set不可以插入重复数据,而multiset可以
- set插入数据的同时会返回插入结果,表示插入是否成功
- multiset不会检测数据,因此可以插入重复数据
总结:
- 如果不允许插入重复数据可以利用set
- 如果需要插入重复数据利用multiset
7. set 容器的排序
- set 容器默认排序规则为从小到大,利用仿函数,可以改变排序规则
- 分为内置数据类型排序和自定义数据类型排序
- 自定义的数据类型就不方便了,自定义排序,完全可以使用结构体排序了
#include <iostream>
#include <string>
#include <set>
using namespace std;
// 可以
struct intComp {
bool operator () (const int& lhs, const int& rhs) const {
return lhs > rhs;
}
};
// 也可以
class Mycompare
{
public:
bool operator () (const int& lhs, const int& rhs) const {
return lhs > rhs;
}
};
// 不可以
bool cmp(int a, int b)
{
return a > b;
}
struct strComp
{
bool operator () (const string& str1, const string& str2) const {
return str1.length() < str2.length();
}
};
int main()
{
int a[] = { 10, 20, 30, 40, 50 };
//set<int, intComp> s1(a, a + 5);
// set<int, cmp> s1(a, a + 5); 不可以
set<int, Mycompare> s1(a, a + 5);
for (auto it = s1.cbegin(); it != s1.cend(); it++)
{
cout << *it << " ";
}
cout << endl;
string b[] = { "apple", "banana", "pear", "orange", "strawberry" };
set<string, strComp > s2 (b, b + 5);
for (auto it = s2.cbegin(); it != s2.cend(); it++)
{
cout << *it << " ";
}
cout << endl;
system("pause");
return 0;
}
输出
50 40 30 20 10
pear apple banana strawberry
自定义数据类型排序
#include <iostream>
#include <string>
#include <set>
using namespace std;
struct person
{
string name;
int age;
person(string name, int age)
{
this->name = name;
this->age = age;
}
// 定义 < 操作符
bool operator<(const person& p) const
{
return this->age < p.age;
}
};
int main()
{
set<person> s;
// 插入数据
s.insert(person("Alice", 30));
s.insert(person("Bob", 25));
s.insert(person("Charlie", 35));
s.insert(person("Alice", 30)); // 不会被插入,因为已经存在
// 输出数据
for (const auto& p : s)
{
cout << "Name: " << p.name << ", Age: " << p.age << endl;
}
return 0;
}