set(树)干货归纳+用法示例

一.set容器特点及应用场景

set是STL中一种标准关联容器。它底层使用弱平衡的搜索树——红黑树实现,插入删除操作时仅仅需要指针操作节点即可完成,不涉及到内存移动和拷贝,所以效率比较高。

1.set特点:

  1. 存储不重复的元素。set中的元素都是唯一的,重复的元素不会被插入。
  2. 自动排序。set中的元素会自动按照一定的顺序进行排序,例如从小到大或从大到小排序(默认升序)。
  3. 快速查找。由于set内部是使用红黑树实现的,查找元素的时间复杂度为O(log n),因此set可以在大量数据中快速查找元素。
  4. 动态插入和删除元素。set支持动态地插入和删除元素,因此在需要动态维护元素集合的场景中非常有用。

2.使用场景:

根据其特点,set适用于需要存储一些唯一元素,并需要按照一定顺序进行排序的场景,例如:

  1. 统计一段文本中不同单词的个数,可以使用set存储单词,并按照字母顺序进行排序。
  2. 存储一个有序的序列,并需要快速查找其中的元素,例如学生成绩排名的存储。
  3. 消除重复的元素,例如去重操作。
  4. 存储一些需要自动排序的元素,并需要支持动态添加和删除,例如任务调度中需要按照任务的优先级进行排序。
  5. 如果需要集合中的元素允许重复那么可以使用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中
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LiuZuqiang_3027

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值