2.8 C++STL set/multiset容器详解


2.8.1 引入

set/multiset容器概念

  • set和multiset是一个集合容器,其中set所包含的元素是唯一的,集合中的元素按一定的顺序自动排列。set采用红黑树变体的数据结构实现,红黑树属于平衡二叉树。在插入操作和删除操作上比vector快。在n个数中查找目标数的效率是 log 2 n

  • set容器中不允许重复元素,multiset允许重复元素。

  • 只提供Insert方法初始化,如下图。

    image-20211012223856316

    set常用API见set 常用API_qq_41050821的博客-CSDN博客

2.8.2 代码示例

#include<iostream>
#include<set>
using namespace std;

//仿函数
class mycompare
{
public:
	bool operator()(int v1,int v2)const
	{
		return v1 > v2;
	}
	//这里要加上const ,原视频vs2019会报错,详情见 https://www.cnblogs.com/qrlozte/p/4437418.html
};

//初始化
void text01()
{
	set<int> s1;//自动进行排序,默认从小到大。
	s1.insert(7);
	s1.insert(2);
	s1.insert(4);
	s1.insert(5);
	s1.insert(1);
	s1.insert(9);

	for (set<int>::iterator it = s1.begin(); it != s1.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;

	//赋值操作
	set<int> s2;
	s2 = s1;

	//删除操作
	s1.erase(s1.begin());
	s1.erase(7);
	for (set<int>::iterator it = s1.begin(); it != s1.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;

	//如何改变默认排序,从大到小。//先序遍历,中序遍历,后序遍历。
	//借助仿函数
	mycompare com;
	com(20, 30);

	set<int, mycompare> s3;//自动进行排序,默认从小到大。
	s3.insert(7);
	s3.insert(2);
	s3.insert(4);
	s3.insert(5);
	s3.insert(1);
	s3.insert(9);
	for (set<int/*,mycompare*/>::iterator it2 = s3.begin(); it2 != s3.end(); it2++)
	{
		cout << *it2 << " ";
	}
	cout << endl;
}

//查找
void text02()
{
	//实值
	set<int> s1;
	s1.insert(7);
	s1.insert(2);
	s1.insert(4);
	s1.insert(5);
	s1.insert(1);
	s1.insert(9);

	set<int>::iterator ret = s1.find(4);//不存在返回end()的值
	if (ret == s1.end())
	{
		cout << "没有找到" << endl;
	}
	else
	{
		cout << "ret:" << *ret << endl;
	}

	//lower_bound(2)找第一个大于等于k的(元素)迭代器值
	ret = s1.lower_bound(2);
	if (ret == s1.end())
	{
		cout << "没有找到" << endl;
	}
	else
	{
		cout << "ret:" << *ret << endl;
	}

	//找第一个大于K的值
	ret = s1.upper_bound(2);
	if (ret == s1.end())
	{
		cout << "没有找到" << endl;
	}
	else
	{
		cout << "ret:" << *ret << endl;
	}

	//equal_range 返回Lower_bound 和 upper_bound值
	pair<set<int>::iterator, set<int>::iterator> myret = s1.equal_range(2);
	//这里用到了pair我们在下面补充对组的相关内容。
	/*myret.first;
	myret.second;*/
	if (myret.first == s1.end())
	{
		cout << "can't find" << endl;
	}
	else
	{
		cout << "myret:" << *myret.first << endl;//返回Lower_bound
	}
	if (myret.second == s1.end())
	{
		cout << "can't find" << endl;
	}
	else
	{
		cout << "myret:" << *myret.second << endl; //返回upper_bound
	}
}

class Person
{
public:
	Person(int age, int id):id(id),age(age){}
public:
	int id;
	int age;
};

class mycompare2
{
public: 
	bool operator()(Person p1, Person p2)const
	{
		return p1.age > p2.age;
	}
};

void text03()
{
	set<Person,mycompare2> sp;

	Person p1(10, 20), p2(30, 40), p3(50, 60);
	sp.insert(p1);
	sp.insert(p2);
	sp.insert(p3);

	Person p4(10, 20);
	for (set<Person, mycompare2>::iterator it = sp.begin(); it != sp.end(); it++)
	{
		cout << (*it).age << " " << (*it).id << endl;
	}

	//查找
	sp.find(p1);
	sp.find(p4);
	auto ret = sp.find(p4);//set<Person,mycompare2>::iterator
	if (ret == sp.end())
	{
		cout << "can't find" << endl;
	}
	else
	{
		cout << "find:" << (*ret).id << " " << (*ret).age << endl;
	}
}

int main()
{
	cout <<"text01:"<< endl;
	text01();
	cout << "text02:" << endl;
	text02();
	cout << "text03:" << endl;
	text03();
	return 0;
}

2.8.3 代码运行结果

image-20211013092413380

2.8.4 对组pair的补充

代码实例
//对组的相关内容补充
#include<iostream>
#include<string>
using namespace std;

void text01()
{
	//创建对组
	//法一
	pair<string, int> pair1(string("number"), 20);
	cout << pair1.first << " " << pair1.second << endl;
	
	//或者pair<string,int> pair2=make_pair("name",30)
	pair<string, int> pair2 = make_pair("name", 30);
	cout << pair2.first << " " << pair2.second << endl;

	//pair赋值
	pair<string, int> pair3 = pair2;
	cout << pair2.first << " " << pair2.second << endl;
}

int main()
{
	text01();
	return 0;
}
运行结果

image-20211013082837467

总结

在刷力扣时,我们发现c++11中的unordered_set也非常常用,我们对比一下就会发现如下结论。

  • c++ std中set与unordered_set区别和map与unordered_map区别类似,其底层的数据结构说明如下:

1、set基于红黑树实现,红黑树具有自动排序的功能,因此map内部所有的数据,在任何时候,都是有序的。

2、unordered_set基于哈希表,数据插入和查找的时间复杂度很低,几乎是常数时间,而代价是消耗比较多的内存,无自动排序功能。底层实现上,使用一个下标范围比较大的数组来存储元素,形成很多的桶,利用hash函数对key进行映射到不同区域进行保存。

详情见c++ set与unordered set的区别 - 阿玛尼迪迪 - 博客园 (cnblogs.com)


谢谢阅读(〃’ ▽ '〃)如有纰漏欢迎指出,觉得还不错就点个赞吧。

posted @ 2022-03-05 16:29  zi_mei  阅读(88)  评论(0)    收藏  举报