目录
set 基本概念
简介:
- 所有元素都会在插入时自动被排序,需要使用头文件 <set>
本质:
- set / multiset 属于关联式容器,底层结构是二叉树实现
set 和 multiset 区别:
- set 不允许容器中有重复的元素
- multiset 允许容器中有重复元素
set 构造和赋值
功能:
- 创建 set 容器以及赋值
构造函数原型:
// 默认构造函数 set<T> st; // 拷贝构造函数 set(const set& st);
赋值函数原型:
// 重载 = 操作符 set& operator=(const set& st);
测试代码:
#include<iostream>
using namespace std;
#include<set>
void PrintSet(const set<int>& s) {
for (set<int>::const_iterator it = s.begin(); it != s.end(); ++it) {
cout << *it << " ";
}
cout << endl;
}
void test() {
set<int>s1;
// 插入数据,只有 insert
s1.insert(10);
s1.insert(30);
s1.insert(20);
// 所有元素在插入时按照从小到大排序
PrintSet(s1); // 10 20 30
s1.insert(10);
// 不允许插入重复值
PrintSet(s1); // 10 20 30
// 拷贝构造
set<int>s2(s1);
PrintSet(s2); // 10 20 30
// 重载 = 操作符
set<int>s3;
s3 = s2;
PrintSet(s3); // 10 20 30
}
int main() {
test();
system("pause");
return 0;
}
运行结果:
set 大小和交换
功能:
- 统计 set 容器大小以及交换 set 容器
函数原型:
// 返回容器中元素的数目 size(); // 判断容器是否为空 empty(); // 交换两个集合容器 swap(st);
测试代码:
#include<iostream>
using namespace std;
#include<set>
void PrintSet(const set<int>& s);
void SetEmpty(const set<int>& s);
void test() {
set<int>s1;
SetEmpty(s1); // 为空
s1.insert(40);
s1.insert(10);
s1.insert(30);
s1.insert(20);
SetEmpty(s1); // 非空
PrintSet(s1); // 10 20 30 40
set<int>s2;
s2.insert(50);
s2.insert(60);
s2.insert(70);
s2.insert(80);
cout << "交换前:" << endl;
PrintSet(s2);
// 交换 s1 和 s2
cout << "交换后:" << endl;
s2.swap(s1);
PrintSet(s2); // 10 20 30 40
}
int main() {
test();
system("pause");
return 0;
}
void SetEmpty(const set<int>& s) {
if (s.empty()) {
cout << "set 为空" << endl;
}
else {
cout << "set 非空" << endl;
}
}
void PrintSet(const set<int>& s) {
for (set<int>::const_iterator it = s.begin(); it != s.end(); ++it) {
cout << *it << " ";
}
cout << endl;
}
运行结果:
set 插入和删除
功能:
- set 容器进行插入数据和删除数据
函数原型:
// 在容器中插入元素 insert(elem); // 清楚所有元素 clear(); // 删除 pos 迭代器所指的元素,返回下一个元素的迭代器 erase(pos); // 删除区间 [beg, end) 的所有元素,返回下一个元素的迭代器 erase(beg, end); // 删除容器中值为 elem 的元素 erase(elem);
测试代码:
#include<iostream>
using namespace std;
#include<set>
void PrintSet(const set<int>& s);
void test() {
set<int>s1;
// insert(elem); 容器中插入元素
s1.insert(20);
s1.insert(10);
s1.insert(30);
s1.insert(40);
PrintSet(s1); // 10 20 30 40
// erase(pos); 删除迭代器所指向的元素
s1.erase(s1.begin()); // 删除 10
PrintSet(s1); // 20 30 40
// erase(beg, end);
s1.erase(++s1.begin(), --s1.end()); // 双向迭代器
PrintSet(s1); // 20 40
// erase(elem); 删除容器中值为 elem 的元素
s1.erase(40);
PrintSet(s1); // 20
// clear(); 清空所有元素
s1.clear(); // 清空操作
PrintSet(s1); // 空
cout << s1.empty() << endl; // 1
}
int main() {
test();
system("pause");
return 0;
}
void PrintSet(const set<int>& s) {
for (set<int>::const_iterator it = s.begin(); it != s.end(); ++it) {
cout << *it << " ";
}
cout << endl;
}
运行结果:
set 查找和统计
功能:
- 对 set 容器进行查找数据以及统计数据
函数原型:
// 查找 key 是否存在,存在返回该元素迭代器,不存在返回 set.end(); find(key); // 统计 key 的元素个数,set 容器返回 0 或 1,multiset 则可以是其他数 count(key);
测试代码:
#include<iostream>
using namespace std;
#include<set>
void PrintSet(const set<int>& s);
void test() {
set<int>s1;
s1.insert(20);
s1.insert(10);
s1.insert(30);
s1.insert(40);
// 查找 find(key);
set<int>::iterator pos = s1.find(10);
if (pos != s1.end()) {
cout << "找到了" << *pos << endl;
}
else {
cout << "未找到" << endl;
}
// 统计 count(key);
int sum1 = s1.count(10);
cout << sum1 << endl; // 1
int sum2 = s1.count(50);
cout << sum2 << endl; // 0
}
int main() {
test();
system("pause");
return 0;
}
void PrintSet(const set<int>& s) {
for (set<int>::const_iterator it = s.begin(); it != s.end(); ++it) {
cout << *it << " ";
}
cout << endl;
}
运行结果:
set 和 multiset 区别
区别:
- set 不可以插入重复元素,multiset 可以
- set 插入数据的同时可以返回插入结果,表示插入是否成功
- multiset 不会检查数据,所以可以插入重复数据
测试代码:
#include<iostream>
using namespace std;
#include<set>
void test() {
set<int>s1;
// set 插入成功会返回插入结果
pair<set<int>::iterator, bool> ret = s1.insert(10);
if (ret.second) {
cout << "第一次插入成功" << endl;
}
else {
cout << "插入失败" << endl;
}
ret = s1.insert(10);
if (ret.second) {
cout << "第一次插入成功" << endl;
}
else {
cout << "插入失败" << endl;
}
// multiset 允许插入重复值
multiset<int>s2;
s2.insert(10);
s2.insert(10);
for (multiset<int>::iterator it = s2.begin(); it != s2.end(); ++it) {
cout << *it << " "; // 10 10
}
cout << endl;
}
int main() {
test();
system("pause");
return 0;
}
运行结果:
pair 对组创建
功能:
- 成对出现的数据,利用对组可以返回两个数据
两种创建方式:
不需要包含头文件
pair<type, type> p (value1, value2); pair<type, type> p = make_pair(value1, value2);
测试代码:
#include<iostream>
#include<string>
using namespace std;
void test() {
// 第一种方式
pair<string, int>p1("李华", 18);
// 获取第一个数据
cout << p1.first << endl;
// 获取第二个数据
cout << p1.second << endl;
// 第二种方式
pair<string, int>p2 = make_pair("张三", 20);
// 获取第一个数据
cout << p2.first << endl;
// 获取第二个数据
cout << p2.second << endl;
}
int main() {
test();
system("pause");
return 0;
}
运行结果:
set 内置类型指定排序规则
set 容器默认排序规则为从小到大,掌握如何更改排序规则
- 运用仿函数,改变排序规则
测试代码:
#include<iostream>
using namespace std;
#include<set>
class MyCompare {
public:
bool operator()(int value1, int value2)const {
return (value1 > value2);
}
};
void test() {
set<int>s1;
s1.insert(10);
s1.insert(30);
s1.insert(50);
s1.insert(20);
s1.insert(40);
// 默认从小到大
for (set<int>::iterator it1 = s1.begin(); it1 != s1.end(); ++it1) {
cout << *it1 << " "; // 10 20 30 40
}
cout << endl;
// 指定排序规则,从大到小
set<int, MyCompare>s2;
s2.insert(10);
s2.insert(30);
s2.insert(50);
s2.insert(20);
s2.insert(40);
for (set<int, MyCompare>::iterator it2 = s2.begin(); it2 != s2.end(); ++it2) {
cout << *it2 << " "; // 40 30 20 10
}
cout << endl;
}
int main() {
test();
system("pause");
return 0;
}
运行结果:
set 自定义类型指定排序规则
仿函数更改自定义数据类型排序规则(必须要指定排序规则)
#include<iostream>
#include<string>
using namespace std;
#include<set>
class Person {
public:
Person(string name, int age) :m_Name(name), m_Age(age) {}
string m_Name;
int m_Age;
};
class MyCompare {
public:
bool operator()(Person p1, Person p2)const {
return (p1.m_Age < p2.m_Age);
}
};
void test() {
// 自定义数据类型都需要指定排序规则
set<Person, MyCompare>Person_Set;
Person p1("李四", 20);
Person p2("张三", 18);
Person p3("王五", 19);
Person p4("李华", 17);
Person_Set.insert(p1);
Person_Set.insert(p2);
Person_Set.insert(p3);
Person_Set.insert(p4);
// set 默认排序(小到大),编译器不知道怎么排序,自定义的数据类型都需要指定排序规则
for (set<Person>::iterator it = Person_Set.begin(); it != Person_Set.end(); ++it) {
cout << "name:" << it->m_Name << " " << "age:" << (*it).m_Age << endl;
}
}
int main() {
test();
system("pause");
return 0;
}
运行结果: