C++ STL set容器详解

set/multiset容器的概念

特点:所有元素都会在插入时自动被排序
本质:set/multiset属于关联式容器,底层结构是用二叉树实现的

set和multiset的区别:
set不允许容器中有重复的元素
multiset允许容器中有重复的元素

注意:使用set或multiset容器时需要包含头文件

#include<set>

1.set的构造和赋值

构造:
set<T> st; //默认构造
set(const set& st); //拷贝构造
赋值:
set& operator=(const set& st);重载赋值运算符

在测试之前,我们先创建一个打印输出的函数,之后在测试时经常用到

void printSet(const set<int>& st)
{
    
    
	cout << "打印set容器:" ;
	for (set<int>::iterator it = st.begin(); it != st.end(); it++)
	{
    
    
		cout << *it << " ";
	}
	cout << endl;
}

测试案例:

void text()
{
    
    
	set<int> s1;      //默认构造

	//set插入数据只有insert的方式
	s1.insert(20);
	s1.insert(30);
	s1.insert(10);
	//s1.insert(10); //容器中已经有相同的元素,插入失败,但并不报错

	//打印s1,是按升序排序好的顺序打印的
	printSet(s1);

	set<int> s2(s1); //拷贝构造
	set<int> s3;  
	s3 = s1;         //重载的赋值运算符
}

测试结果:
在这里插入图片描述

2.set的大小和交换

函数原型:
size(); //返回容器中元素个数
empty(); //判断容器是否为空,为空返回1,否则返回0
swap(); //交换两个容器

测试案例:

void text()
{
    
    
	set<int> s1, s2;
	//empty()
	if (s1.empty())  //如果s1为空
	{
    
    
		s1.insert(1);
		s1.insert(5);
		s1.insert(3);
	}
	if (s2.empty())
	{
    
    
		s2.insert(10);
		s2.insert(50);
		s2.insert(30);
		s2.insert(80);
	}
	//size()
	cout << "s1的大小为:" << s1.size() << endl;
	cout << "s2的大小为:" << s2.size() << endl;

	//swap()
	cout << "交换前:" << endl;
	printSet(s1);
	printSet(s2);
	s1.swap(s2);//交换s1和s2
	cout << "交换后:" << endl;
	printSet(s1);
	printSet(s2);
}

测试结果:
在这里插入图片描述

3.set的插入和删除

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

测试案例:

void text()
{
    
    
	set<int> s;
	//insert()
	s.insert(10);
	s.insert(8);
	s.insert(15);
	s.insert(2);
	printSet(s);
	//erase()
	s.erase(s.begin());   //删除首个元素,由于set容器插入时已经升序排序好了,此时删除的是最小的元素
	printSet(s);
	s.erase(10);          //删除为10的元素
	printSet(s);

	//清空
	s.clear(); //等价于s.erase(s.begin(),s.end());
	printSet(s);
}

测试结果:
在这里插入图片描述

4.set的查找和统计

函数原型:
find(elem); //查找容器中elem的位置,如果elem存在返回该元素的迭代器,不存在返回set.end();
count(elem); //统计的容器中元素elem的个数,set容器元素个数只能是0或1,multiset容器可能大于1

测试案例:

void text()
{
    
    
	set<int> s;
	s.insert(5);
	s.insert(3);
	s.insert(4);
	s.insert(2);
	printSet(s);
	//find()
	set<int>::iterator pos = s.find(5);
	if (pos != s.end())
	{
    
    
		cout << "找到元素:" << *pos << endl;
	}
	else cout << "没有该元素" << endl;

	//count()
	cout << "元素5" << "有" << s.count(5) << "个" << endl;
}

测试结果:
在这里插入图片描述

5.set和multiset的区别

区别:

  • set不允许插入相同的数据,而multiset允许
  • set插入数据的同时会返回插入结果,表示插入是否成功,该结果是用对组pair接收的
  • multiset不会检测数据,因此可以插入相同数据

对组pair下面会详细介绍,现在先使用一下

测试案例:

void text()
{
    
    
	set<int> s;
	//用pair接收s的插入结果
	pair < set<int>::iterator, bool > ret = s.insert(10);
	if (ret.second)//ret的第二个类型数据,即bool类型,若为真则插入成功
	{
    
    
		cout << "插入成功" << endl;
	}
	else cout << "插入失败" << endl;
	ret = s.insert(10);
	if (ret.second)//ret的第二个类型数据,即bool类型,若为真则插入成功
	{
    
    
		cout << "插入成功" << endl;
	}
	else cout << "插入失败" << endl;

	//multiset可以重复插入相同元素,不检测插入结果
	multiset<int> ms;
	ms.insert(10);
	ms.insert(10);
	ms.insert(10);
	cout << "打印multiset容器:";
	for (multiset<int>::iterator it = ms.begin(); it != ms.end(); it++)
	{
    
    
		cout << *it << " ";
	}
	cout << endl;
}

测试结果:
在这里插入图片描述

6.pair对组的创建

对组的概念:成对出现的数据

两种创建方式:
pair<T1,T2> p(value1,value2);
pair<T1,T2> p = make_pair(value1,value2);
使用:
p.first; //返回对组的第一个类型的数据
p.second; //返回对组的第二个类型的数据

值得一提的是使用pair并不需要头文件

测试案例:

void text()
{
    
    
	//创建
	pair<string, int> p1("张三", 25);
	pair<string, int> p2 = make_pair("李四", 30);
	//使用
	cout << "姓名:" << p1.first << " 年龄:" << p1.second << endl;
	cout << "姓名:" << p2.first << " 年龄:" << p2.second << endl;
}

测试结果:
在这里插入图片描述

7.set容器的排序规则

我们已经知道,在我们插入数据时,set容器会自动给我们排序好,默认情况是由小到大,也就是升序排序。
你应该会有疑惑了:

  • 能不能改变排序规则,让其降序序排序
  • 定义一个类,它有多个成员变量,那我们到底按照那个成员来排序呢

对于以上两种情况我们通常引入仿函数,自定义一个排序规则,如何排序由我们自己决定

测试案例:对内置数据类型排序

class Mycompare
{
    
    
public:
	bool operator()(int v1,int v2) const //重载() 运算符
	{
    
    
		return v1 > v2;  //指定排序规则,从大到小,也就是降序排序
	}
};
void text1()
{
    
    
	set<int,Mycompare> s1;
	s1.insert(10);
	s1.insert(50);
	s1.insert(30);
	s1.insert(40);
	cout << "打印降序排序的set容器:" << endl;
	for (set<int, Mycompare>::iterator it = s1.begin(); it != s1.end(); it++)
	{
    
    
		cout << *it << " ";
	}
	cout << endl;
}

测试结果:
在这里插入图片描述

测试案例:对自定义数据类型排序

class Person
{
    
    
public:
	string m_name;
	int m_age;
	Person(string name, int age) :m_name(name), m_age(age) {
    
     }
};
class Mycompare
{
    
    
public:
	bool operator()(const Person& p1,const Person& p2) const //重载() 运算符
	{
    
    
		return p1.m_age > p2.m_age; 
	}
};
void text1()
{
    
    
	set<Person,Mycompare> s1;
	Person p1("张三", 25);
	Person p2("李四", 20);
	Person p3("王五", 30);
	s1.insert(p1);
	s1.insert(p2);
	s1.insert(p3);
	cout << "按照年龄大小降序排序:" << endl;
	for (set<Person, Mycompare>::iterator it = s1.begin(); it != s1.end(); it++)
	{
    
    
		cout << "姓名:" << (*it).m_name << "  年龄:" << (*it).m_age << endl;
	}
}

测试结果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_52324409/article/details/121280952
今日推荐