【STL】set&multiset

头文件:

#include<set>
  • 序列式容器:元素位置和插入元素的时机有关系,什么时候插入元素决定了元素在什么位置,位置和本身值的大小没有关系
  • 关联式容器:元素位置和元素值有关,和插入元素的时机没有关系

set/multiset属于关联式容器,底层结构使用二叉树实现的。它们的特点是:所有的元素在插入时会自动被排序。 而set与multiset容器的区别就是:set容器中不允许有重复的元素,而multiset允许容器中有重复的元素。

  • set容器主要是为了实现去重的功能,默认为升序排序(从小到大)
  • set是一个集合容器,其中所包含的元素是唯一的,集合中的元素按一定的顺序排列。元素插入过程是按排序规则插入,所以不能指定插入位置
  • set采用红黑树变体的数据结构实现,红黑树属于平衡二叉树,在插入操作和删除操作上(Olog2 n)比vector(O(n))快
  • set不可以直接存取元素(不可以使用at.(pos)和[]操作符)
  • 不可以直接修改set或multiset容器中的元素值,因为该类容器是自动排序的,如果希望修改一个元素值,必须先删除原有的元素,再插入新的元素

注意:set容器没有push_back, pop_back这两种插入接口,只能用insert函数进行插入。如果向set容器中插入相同元素,不会报错,但是打印的时候会自动滤去多余的元素,一个元素只能有一个,而且打印结果是排好序了的。

Note:the set container has no push_back and pop_back these two kinds of insertion interface, can only use the insert function to insert.if the same element is inserted into the set container, no error will be reported, but the redundant elements will be automatically filtered out when printing. There can only be one element, and the printing results are in good order.

set构造和赋值

函数描述
set< T > st默认构造函数
set(const set &st)拷贝构造函数
set& operator=(const set &st)重载等号操作符

实例:

#include<iostream>
#include<set>
using namespace std;
//set容器构造和赋值
void printSet(set<int>&s) {
	for (auto it = s.begin(); it != s.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}
int main() {
	set<int> s1;
	//该容器插入数据只有insert方式
	s1.insert(10);
	s1.insert(40);
	s1.insert(30);
	s1.insert(20);
	s1.insert(30);
	//遍历容器
	//所有的元素在插入的时候会自动升序排序
	//set容器不允许插入重复值
	printSet(s1);//10 20 30 40
	//拷贝构造
	set<int> s2(s1);
	printSet(s2);
	//赋值
	set<int> s3;
	s3 = s2;
	printSet(s3);
	return 0;
}

注意:set容器插入时用insert,并且传入的是元素而不是迭代器。你可以这么理解,就是set容器中插入元素并不是顺序排列的,而是根据元素的大小进行顺序排列的,因此插入元素的位置只有在插入容器之后才能确定,因此不能传入迭代器。因此,这里需要将set集合的插入与vector容器的插入进行一定程度的区分。

set容器的大小与交换

函数描述
size()返回容器中元素的数目
empty()判断容器是否为空
swap(st)交换两个集合容器

实例:

#include<iostream>
#include<set>
using namespace std;
void printSet(set<int>& s) {
	for (auto it = s.begin(); it != s.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}
int main() {
	set<int> s1;
	//插入数据
	s1.insert(10);
	s1.insert(30);
	s1.insert(20);
	s1.insert(40);
	//打印容器
	printSet(s1);
	//判断容器是否为空
	if (s1.empty()) {
		cout << "s1为空" << endl;
	}
	else
	{
		cout << "s1不为空" << endl;
		cout << "s1的大小为:" << s1.size() << endl;
	}
	//交换容器
	set<int> s2;
	s2.insert(50);
	s2.insert(80);
	s2.insert(70);
	s2.insert(60);
	s2.insert(90);
	cout << "交换前:" << endl;
	printSet(s1);
	printSet(s2);

	s1.swap(s2);//交换容器
	cout << "交换后:" << endl;
	printSet(s1);
	printSet(s2);
	return 0;
}

set容器插入与删除

函数描述
insert(elem)在容器中插入元素
clear()清除所有元素
erase(pos)删除pos迭代器所指的元素,返回下一个元素的迭代器
erase(beg,end)删除区间[beg,end)的所有元素,返回下一个元素的迭代器
erase(elem)删除容器中值为elem的元素

实例:

#include<iostream>
#include <set>
using namespace std;
void printSet(set<int> &s) {
	for (auto it = s.begin(); it != s.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}
//set插入与删除
int main() {
	set<int> s1;
	//插入元素
	s1.insert(10);
	s1.insert(30);
	s1.insert(40);
	s1.insert(20);//插入后自动排序
	printSet(s1);
	//删除
	s1.erase(s1.begin());
	printSet(s1);
	//删除重载的版本
	s1.erase(30);
	printSet(s1);
	//清除
	s1.clear();//等价于s1.erase(s1.begin(), s1.end());
	printSet(s1);
	return 0;
}

set容器的查找与统计

函数描述
find(key)查找key是否存在,若存在返回该键的元素的迭代器;若不存在,返回set.end()
count(key)统计key的元素个数

实例:

#include<iostream>
#include <set>
using namespace std;
//set容器的查找与统计
int main() {
	set<int> s1;
	//插入数据
	s1.insert(20);
	s1.insert(30);
	s1.insert(10);
	s1.insert(40);
	//查找
	set<int>::iterator pos = s1.find(30);
	if (pos!= s1.end()) {//找到元素
		cout << "找到该元素:" << *pos<< endl;
	}
	else {
		cout << "未找到该元素" << endl;
	}
	//统计
	//这里需要注意 set容器不予许出现重复的元素
	//因此count返回的值只能为0或者1
	//统计30的个数
	s1.insert(30);
	s1.insert(30);
	int num = s1.count(30);
	cout << "30的个数为:" << num << endl; //1
	return 0;
}

注意:由于set容器不允许出现重复的元素,因此统计count函数只能返回0或者1,因此count函数可以用来判断某个元素是否存在于set容器中。

set与multiset容器的区别

  • set容器不予许出现重复数据,而multiset可以;
  • set插入数据的同时会返回插入结果,表示插入成功;
  • multiset不会检测数据,因此可以插入重复数据。

实例:

#include<iostream>
#include<set>
using namespace std;
int main() {
	set<int>s;
	pair<set<int>::iterator,bool> res=s.insert(10);
	if (res.second) {
		cout << "第一次插入10成功";
	}
	else {
		cout << "第一次插入10失败";
	}
	cout << endl;
	res = s.insert(10);
	if (res.second) {
		cout << "第二次插入10成功";
	}
	else {
		cout << "第二次插入10失败";
	}
	cout << endl;
	multiset<int> ms;//允许插入重复的值
	ms.insert(10);
	ms.insert(10);
	//遍历
	for (multiset<int>::iterator it = ms.begin(); it != ms.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
	return 0;
}

注意:对于set容器的插入会返回一个pair二元组得的数据类型,而multiset容器的插入只会返回一个迭代器。

pair对组创建

成对出现的数据,利用对组可以返回两个数据。对组(pair)将一对值组合成一个值,这一对值可以具有不同的数据类型,两个值可以分别用pair的两个公有属性first和second访问。

pair对组主要有两种创建方式:

  • pair<type,type> p(value1,value2);
  • pair<type,type> p=make_pair(value1,value2);

实例:

#include<iostream>
#include<string>
using namespace std;
//pair对组的使用
int main() {
	//第一种创建方式
	//pair<type,type> p(value1,value2);
	pair<string, int>p("Tom", 20); 
	cout << "姓名:" << p.first << " 年龄:" << p.second << endl;
	//第二种方式创建对组
	//pair<type,type> p=make_pair(value1,value2);
	pair<string, int> p2 = make_pair("Nancy", 22);
	cout << "姓名:" << p2.first << " 年龄:" << p2.second << endl;
	return 0;
}

set自定义排序规则

#include<iostream>
#include<set>
using namespace std;
/*set container sort*/
class MyCompare   // This class MyCmp is an imitation function
{
public:
	bool operator()(int v1, int v2) const  // 后面一定要加这个const表示这个函数是常函数,不然vs2019会报错
	{
		return v1 > v2;
	}
};
void PrintSet(const set<int>& s)
{
	for (set<int>::const_iterator it = s.begin(); it != s.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}
int main()
{
	set<int>s1;
	// Data insert
	s1.insert(10);
	s1.insert(30);
	s1.insert(40);
	s1.insert(50);
	s1.insert(20);
	cout << "s1: " << endl;
	// 10 20 30 40 50 
	PrintSet(s1);   // The default rule is from small to large
	cout << endl;
	// Specify rules from small to large
	// 自定义排序值从大到小 
	set<int, MyCompare>s2;
	s2.insert(10);
	s2.insert(30);
	s2.insert(40);
	s2.insert(50);
	s2.insert(20);
	cout << "s2: " << endl;
	// 50 40 30 20 10
	for (set<int, MyCompare>::iterator it = s2.begin(); it != s2.end(); it++) // Different definitions have different iterators
	{
		cout << *it << " ";
	}
	cout << endl;
	return 0;
}

参考博文:

https://blog.csdn.net/qq_51447436/article/details/126687920

https://blog.csdn.net/qq_51447496/article/details/127593246

  • 14
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值