2.set
一.set容器特点及应用场景
set是STL中一种标准关联容器。它底层使用弱平衡的搜索树——红黑树实现,插入删除操作时仅仅需要指针操作节点即可完成,不涉及到内存移动和拷贝,所以效率比较高。
1.set特点:
- 存储不重复的元素。set中的元素都是唯一的,重复的元素不会被插入。
- 自动排序。set中的元素会自动按照一定的顺序进行排序,例如从小到大或从大到小排序(默认升序)。
- 快速查找。由于set内部是使用红黑树实现的,查找元素的时间复杂度为O(log n),因此set可以在大量数据中快速查找元素。
- 动态插入和删除元素。set支持动态地插入和删除元素,因此在需要动态维护元素集合的场景中非常有用。
2.使用场景:
根据其特点,set适用于需要存储一些唯一元素,并需要按照一定顺序进行排序的场景,例如:
- 统计一段文本中不同单词的个数,可以使用set存储单词,并按照字母顺序进行排序。
- 存储一个有序的序列,并需要快速查找其中的元素,例如学生成绩排名的存储。
- 消除重复的元素,例如去重操作。
- 存储一些需要自动排序的元素,并需要支持动态添加和删除,例如任务调度中需要按照任务的优先级进行排序。
- 如果需要集合中的元素允许重复那么可以使用multiset,set不允许数据冗余,而multiset允许数据冗余。
二.set容器基本操作
#include <set>
set<int> s;
set<int> s;
int elem;
s.begin();//返回set容器的第一个元素
s.end(); //返回set容器的最后一个迭代器(最后一个元素的后一个)
s.rbegin();//返回set容器的逆序第一个元素
s.rend();//返回set容器的逆序第一个迭代器(最后一个元素的后一个)
s.clear(); //清空set容器中的所有的元素
s.empty(); //判断set容器是否为空
s.max_size(); //返回set容器可能包含的元素最大个数
s.size(); //返回当前set容器中的元素个数
s.find(elem); //返回值是迭代器类型
s.count(elem); //elem的个数,要么是1,要么是0,multiset可以大于一
s.insert(elem);//集合s中增加元素elem
s.erase(elem);//集合s中增删除元素elem
//输出集合元素
void set_print(set<int >s) {
cout << "set元素为:";
for (set<int>::iterator it = s.begin(); it != s.end(); it++)
cout << *it << " ";
cout << endl;
}
三.set用法示例
3.容器创建(5种方法)
#include <set>
#include <functional>
using namespace std;
set<int> s;
int main() {
一.set<int > seta; //默认是小于比较器less<int>的set
二.set<int, greater<int> > setb; //创建一个带大于比较器的set,需包含头文件functional
int a[5] = { 1,2,3,4,5 };
三.set<int ,greater<int>> setc(a, a + 5); //数组a初始化一个set;
cout << "setc元素为:";
for (set<int>::iterator it = setc.begin(); it != setc.end(); it++)
cout << *it << " ";
cout << endl;
四.set<int > setd(setc.begin(), setc.end()); //setc初始化一个set
//上述两例均为区间初始化
五.set<int > sete(setd); //拷贝构造创建set
cout << "sete元素为:";
for (set<int>::iterator it = sete.begin(); it != sete.end(); it++)
cout << *it << " ";
}
2.插入元素
#include "pch.h"
#include <iostream>
#include <set>
using namespace std;
set<int >s;
void set_print(set<int >s) {
cout << "set元素为:";
for (set<int>::iterator it = s.begin(); it != s.end(); it++)
cout << *it << " ";
cout << endl;
}
int main() {
s.insert(1);
s.insert(2);
s.insert(5);
set_print(s);
s.insert(2); //set只允许用一个值出现一次,要插入相同元素请用multiset
set_print(s);
int a[4] = { 11,12,13,14 };
s.insert(a, a + 4); //将区间[a, a+4]里的元素插入容器
set_print(s);
}
3.删除元素
#include "pch.h"
#include <iostream>
#include <set>
using namespace std;
set<int >s;
void set_print(set<int >s) {
cout << "set元素为:";
for (set<int>::iterator it = s.begin(); it != s.end(); it++)
cout << *it << " ";
cout << endl;
}
int main() {
for (int i = 1; i < 11; i++) {
s.insert(i);
}
set_print(s);
s.erase(9); //根据元素删除
set_print(s);
set<int>::iterator ita = s.begin();
set<int>::iterator itb = s.begin();
s.erase(ita); //删除迭代器指向位置的元素
set_print(s);
ita = s.begin();
itb = s.begin();
itb++; itb++;
s.erase(ita, itb); //删除区间[ita,itb)的元素
set_print(s);
s.clear();
}
4.查找元素
#include "pch.h"
#include <iostream>
#include <set>
using namespace std;
set<int >s;
void set_print(set<int >s) {
cout << "set元素为:";
for (set<int>::iterator it = s.begin(); it != s.end(); it++)
cout << *it << " ";
cout << endl;
}
int main() {
s.insert(1);
s.insert(2);
s.insert(5);
set_print(s);
if (s.find(2) != s.end())
cout << "2 is existent" << endl;
else
cout << "2 is non-existent" << endl;
if (s.find(3) == s.end())
cout << "3 is non-existent" << endl;
else
cout << "3 is existent" << endl;
}
5.set其他操作
- 1.返回特定值
s.lower_bound() 返回第一个大于或等于给定关键值的元素
s.upper_bound() 返回第一个大于给定关键值的元素
s.equal_range() 返回一对定位器,分别表示 第一个大于或等于给定关键值的元素 和 第一个大于给定关键值
的元素,这个返回值是一个pair类型,如果这一对定位器中哪个返回失败,就会等于s.end()
#include "pch.h"
#include <iostream>
#include <set>
using namespace std;
int main() {
set<int> s;
s.insert(1);
s.insert(2);
s.insert(5);
cout << "lower_bound & upper_bound test:" << endl;
cout << "第一个大于或等于3的元素: " << *s.lower_bound(3) << endl;
cout << "第一个大于或等于2的元素: " << *s.lower_bound(2) << endl;
cout << "第一个大于2的元素: " << *s.upper_bound(2) << endl;
cout << "equal_range test:" << endl;
cout << "第一个大于或等于2的元素: " << *s.equal_range(2).first << endl;
cout << "第一个大于2的元素: " << *s.equal_range(2).second << endl;
return 0;
}
- 2.判断元素是否在set中 & 判断set是否为空
#include "pch.h"
#include <iostream>
#include <set>
#include <functional>
using namespace std;
int main() {
set<int > s;
if (s.empty()) cout << "容器为空" << endl;
s.insert(1);
if (!s.empty()) cout << "容器不为空" << endl;
if (s.count(1)) cout << "1在容器中" << endl;
if (!s.count(2)) cout << "2不在容器中" << endl;
return 0;
}
3.自定义集合排序函数
#include "pch.h"
#include <iostream>
#include <set>
#include <functional>
using namespace std;
struct cmp {
bool operator () (const int &a, const int &b) {
return a > b;
}
};
set<int, cmp>s; //自定义排序函数构造set
void set_print(set<int, cmp>s) { //输入参数切记需要对应修改
cout << "set元素为:";
for (set<int>::iterator it = s.begin(); it != s.end(); it++)
cout << *it << " ";
cout << endl;
}
int main() {
s.insert(1);
s.insert(2);
s.insert(6);
set_print(s);
return 0;
}
四.使用STL中的algorithm库对set进行操作
需要注意的是,以下的操作都需要包含algorithm库和set头文件。
1.查找元素:
auto it = find(s.begin(), s.end(), val); // 查找值为val的元素,返回迭代器
if (it != s.end()) {
// 找到元素
} else {
// 没有找到元素
}
2.统计元素个数:
int count = std::count(s.begin(), s.end(), val); // 统计值为val的元素个数
3.移除元素:
s.erase(val); // 移除值为val的元素
4.合并两个set:
std::set<int> s1 = {...};
std::set<int> s2 = {...};
std::set<int> s3;
std::merge(s1.begin(), s1.end(), s2.begin(), s2.end(), std::inserter(s3, s3.begin())); // 将s1和s2合并到s3中
5.求交集:
std::set<int> s1 = {...};
std::set<int> s2 = {...};
std::set<int> s3;
std::set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(), std::inserter(s3, s3.begin())); // 求s1和s2的交集,结果存入s3中
6.求并集:
std::set<int> s1 = {...};
std::set<int> s2 = {...};
std::set<int> s3;
std::set_union(s1.begin(), s1.end(), s2.begin(), s2.end(), std::inserter(s3, s3.begin())); // 求s1和s2的并集,结果存入s3中