STL-----set容器的操作以及pair

#include<iostream>
#include<algorithm>
#include<list>
#include<string>
#include<set>

using namespace std;


//使用set或者multiset的头文件都是se

//set的基本概念:
/*
Set的特性是。所有元素都会根据元素的键值自动被排序。(关联式容器自动排好序,序列式容器按插入顺序存放)
Set的元素不像map那样可以同时拥有实值和键值,set的元素即是键值又是实值。Set不允许两个元素有相同的键值。
我们可以通过set的迭代器改变set元素的值吗?
不行,因为set元素值就是其键值,关系到set元素的排序规则。如果任意改变set元素值,会严重破坏set组织。
换句话说,set的iterator是一种const_iterator.
set拥有和list某些相同的性质,当对容器中的元素进行插入操作或者删除操作的时候,操作之前所有的迭代器,
在操作完成之后依然有效,被删除的那个元素的迭代器必然是一个例外。
*/


//multiset容器基本概念:
/*
multiset特性及用法和set完全相同,唯一的差别在于它允许键值重复。
set和multiset的底层实现是红黑树,红黑树为平衡二叉树的一种。
*/

/*
set构造函数
set<T> st;//set默认构造函数:
mulitset<T> mst; //multiset默认构造函数:
set(const set &st);//拷贝构造函数
*/
/*
set赋值操作
set& operator=(const set &st);//重载等号操作符
swap(st);//交换两个集合容器
*/
/*
 set插入和删除操作
insert(elem);//在容器中插入元素。
clear();//清除所有元素
erase(pos);//删除pos迭代器所指的元素,返回下一个元素的迭代器。
erase(beg, end);//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
erase(elem);//删除容器中值为elem的元素。
*/

void printSet(const set<int> &s)
{
	for (set<int>::const_iterator it = s.begin(); it != s.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

void test01()
{
	set<int> s1;

	s1.insert(5);
	s1.insert(1);
	s1.insert(9);
	s1.insert(3);
	s1.insert(7);

	printSet(s1);


	//size函数:
	if (!s1.size()) {
		cout << "s1为空" << endl;
	}
	else {
		cout << "s1不为空" << endl;
	}

	//删除操作:
	s1.erase(s1.begin());//还剩3.5.7.9
	printSet(s1);
	s1.erase(3);//5.7.9,删除这个数;
	printSet(s1);
}


/*
set查找操作
find(key);//查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
count(key);//查找键key的元素个数
lower_bound(keyElem);//返回第一个key>=keyElem元素的迭代器。
upper_bound(keyElem);//返回第一个key>keyElem元素的迭代器。
equal_range(keyElem);//返回容器中key与keyElem相等的上下限的两个迭代器。
*/
void test02()
{
	//对于set,没有value和key之分;key==value;
	set<int> s1;

	s1.insert(5);
	s1.insert(1);
	s1.insert(9);
	s1.insert(3);
	s1.insert(7);

	//查找操作:
	set<int>::iterator pos = s1.find(3);//在set中查找3这个数;
	if (pos != s1.end()) {
		cout << "找到了这个数,这个数是:" << *pos << endl;
	}
	else {
		cout << "没找到" << endl;
	}

	pos = s1.find(2);//在set中查找2这个数;
	if (pos != s1.end()) {
		cout << "找到了这个数,这个数是:" << *pos << endl;
	}
	else {
		cout << "没找到" << endl;
	}

	//count(key);//查找键key的元素个数
	//对于set而言,结果就是0或1;

	int num = s1.count(1);
	cout << "1的个数为: " << num << endl;//输出1
	num = s1.count(2);
	cout << "2的个数为: " << num << endl;//输出0

	//lower_bound(keyElem);//返回第一个key>=keyElem元素的迭代器。
	set<int>::iterator it = s1.lower_bound(3);
	if (it != s1.end()) {
		cout << "第一个>=3的元素是: " << *it << endl;
	}
	else {
		cout << "未找到" << endl;
	}

	//upper_bound(keyElem);//返回第一个key>keyElem元素的迭代器。
	set<int>::iterator it_1 = s1.upper_bound(3);
	if (it_1 != s1.end()) {
		cout << "第一个>3的元素是: " << *it_1 << endl;
	}
	else {
		cout << "未找到" << endl;
	}

	//equal_range(keyElem);//返回容器中key与keyElem相等的上下限的两个迭代器。
	//上下限,一个是lower_bound,一个是upper_bound;
	//返回值为:_NODISCARD _Paircc 
	//using _Paircc = pair<const_iterator, const_iterator>;
	//pair;
	pair<set<int>::iterator, set<int>::iterator> ret=s1.equal_range(3);
	//获取第一个值:
	if (ret.first == s1.lower_bound(3)) {
		cout << "找到了下限:" << *(ret.first) << endl;
	}
	else {
		cout << "没有找到下限" << endl;
	}
	if (ret.second == s1.upper_bound(3)) {
		cout << "找到了上限:" << *(ret.second) << endl;
	}
	else {
		cout << "没有找到上限" << endl;
	}
}

//补充:对组的概念:
/*
对组(pair)将一对值组合成一个值,这一对值可以具有不同的数据类型,两个值可以分别用pair的两个公有属性first和second访问。
类模板:template <class T1, class T2> struct pair.
*/

void test03()
{
	//创建方式一:
	pair<string, int> P1 ("Tom", 100);

	//取值:
	cout << (P1.first)<< endl;
	cout << (P1.second) << endl;
	//与上面不同,上面的pair创建的是迭代器(指针);

	//创建方式二:
	pair<string, int>p2 = make_pair("Jerry", 99);
	cout << p2.first << endl;
	cout << p2.second << endl;
}

//set不允许插入重复的key值:
//multiset允许插入重复值:
void test04()
{
	set<int> s;
	s.insert(10);
	s.insert(10);

	printSet(s);//可以编译成功并运行,只是显示的只有一个10;

	//insert的源码:
	//_Pairib insert(value_type&& _Val)
	//using _Pairib = pair<iterator, bool>;
	//bool表示插入是否成功;
	//有以下:
	set<int> s2;
	pair<set<int>::iterator, bool>ret = s2.insert(10);

	if (ret.second) {
		cout << "插入成功" << endl;
	}
	else {
		cout << "插入失败" << endl;
	}
	//插入成功
	printSet(s2);

	ret = s2.insert(10);
	if (ret.second) {
		cout << "插入成功" << endl;
	}
	else {
		cout << "插入失败" << endl;
	}
	//插入失败
	printSet(s2);

	ret = s2.insert(20);
	if (ret.second) {
		cout << "插入成功" << endl;
	}
	else {
		cout << "插入失败" << endl;
	}
	//插入成功
	printSet(s2);
}


//指定set的排序规则:
//仿函数:
//函数不能做类型,class可以做类型;
class myCompare
{
public:
	//重载():
	bool operator()(int v1, int v2)
	{
		return v1 > v2;
	}
};

void printSet_2(const set<int ,myCompare> &s)
{
	for (set<int, myCompare>::iterator it = s.begin(); it != s.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}

//set排序:
void test05()
{
	set<int> s1;

	s1.insert(5);
	s1.insert(1);
	s1.insert(9);
	s1.insert(3);
	s1.insert(7);

	printSet(s1);
	//从小到大排序;


	//从大到小排序:
	//set在数据插入后不允许改变,所以只能在插入之前确定排序顺序;

	set<int, myCompare> s2;

	s2.insert(5);
	s2.insert(1);
	s2.insert(9);
	s2.insert(3);
	s2.insert(7);

	printSet_2(s2);
}

//set插入自定义数据类型:
class Person
{
public:
	Person(string name,int age) :m_Name(name),m_Age(age){}

	string m_Name;
	int m_Age;
};

class myCompare_2
{
public:
	bool operator()(const Person &p1,const Person &p2)
	{
		return p1.m_Age > p2.m_Age;
	}
};

void test06()
{
	Person p1("asdasd", 100);
	Person p2("asd", 12130);
	Person p3("asd\sdasd", 140);
	Person p4("asdsadasdasd", 2340);

	set<Person,myCompare_2> s;
	s.insert(p1);
	s.insert(p2);
	s.insert(p3);
	s.insert(p4);

	//打印:
	for (set<Person, myCompare_2>::iterator it = s.begin(); it != s.end(); it++) {
		cout << "姓名是:" << it->m_Name << "   年龄是:" << it->m_Age << endl;
	}
}

int main()
{
	test01();
	test02();
	test03();
	test04();
	test05();
	test06();
	system("pause");
	return 0;
}
发布了158 篇原创文章 · 获赞 37 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/XUCHEN1230/article/details/86549320