C++ STL(八):set/multiset容器


1 set基本概念

set / multiset属于关联式容器,底层结构采用红黑树实现。
特点:插入无序元素时,会自动完成排序。(输入无序序列,输出有序)

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


2 set构造函数和赋值【operator=】

作用:创建set容器及赋值。

注:使用set容器时,需包含头文件#include <set>

构造函数
set<T> st;:默认无参构造函数,采用类模板实现。
set(const set &st);:拷贝构造函数,使用已有set对象初始化新的对象。


赋值操作
set& operator=(const set &st);:重载赋值运算符,使用目标set容器,对当前set容器赋值。

示例:set构造函数和赋值

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

//函数模板:遍历set容器的通用函数
template<typename T>
void printSet(const set<T>& s) {
    
    	//形参使用const,避免被修改
	//形参使用const后,遍历时需使用只读迭代器const_iterator
	//使用typename关键字,防止编译器报错:C2760(语法错误,意外标记“标识符”)
	for (typename set<T>::const_iterator it = s.begin(); it != s.end(); it++) {
    
    
		cout << *it << " ";
	}
	cout << endl;
}

int main() {
    
    
	//1.默认无参构造
	set<int> s;

	//插入元素
	s.insert(9);
	s.insert(1);
	s.insert(7);
	s.insert(3);
	s.insert(5);

	//自动排序
	printSet<int>(s);	//1	3 5 7 9

	//2.拷贝构造
	set<int> s1(s);
	printSet<int>(s1);	//1	3 5 7 9

	//3.赋值操作
	set<int> s2;
	s2 = s1;
	printSet<int>(s2);	//1	3 5 7 9

	return 0;
}

3 set大小【size()】和交换【swap()】

大小操作
size();:获取容器的大小,即元素个数
empty();:判断容器是否为空。

注:set集合不允许出现重复元素,故不支持resize()操作,避免指定长度变大时,填充默认值或指定值时插入重复元素。


交换操作
swap(st);:将目标set容器st与自身的元素互换。

示例

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

//函数模板:遍历set容器的通用函数
template<typename T>
void printSet(const set<T>& s) {
    
    	//形参使用const,避免被修改
	//形参使用const后,遍历时需使用只读迭代器const_iterator
	//使用typename关键字,防止编译器报错:C2760(语法错误,意外标记“标识符”)
	for (typename set<T>::const_iterator it = s.begin(); it != s.end(); it++) {
    
    
		cout << *it << " ";
	}
	cout << endl;
}

int main() {
    
    
	//默认无参构造
	set<int> s1;

	//插入元素
	s1.insert(9);
	s1.insert(1);
	s1.insert(7);
	s1.insert(3);
	s1.insert(5);

	//empty() 判断是否为空
	cout << (s1.empty() ? "空" : "非空") << endl;		//非空
	//size() 大小
	cout << s1.size() << endl;	//5

	/* 交换操作 */
	set<int> s2;
	s2.insert(4);
	s2.insert(8);
	s2.insert(6);
	s2.insert(2);

	cout << "交换前:" << endl;
	printSet(s1);	//1 3 5 7 9
	printSet(s2);	//2 4 6 8

	//swap() 交换操作
	s1.swap(s2);

	cout << "交换后:" << endl;
	printSet(s1);	//2 4 6 8
	printSet(s2);	//1 3 5 7 9

	return 0;
}

4 set插入【insert()】和删除【erase()、clear()】

(1)插入元素:使用成员函数insert(..)向set容器插入元素。

函数原型
insert(elem);:向set容器插入元素elem


(2)删除元素:使用成员函数erase(..)clear(..)删除set容器中的元素。

函数原型
erase(const_iterator pos);:删除迭代器指向位置的元素。
erase(const_iterator start, const_iterator end);:删除迭代器指向位置[start, end)区间的所有元素。
erase(elem);:删除容器中值为elem元素。
clear();:清空容器中的所有元素

注:清空容器的所有元素,s.clear();等价于s.erase(s.begin(), s.end());

示例:set容器插入和删除元素

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

//函数模板:遍历set容器的通用函数
template<typename T>
void printSet(const set<T>& s) {
    
    	//形参使用const,避免被修改
	//形参使用const后,遍历时需使用只读迭代器const_iterator
	//使用typename关键字,防止编译器报错:C2760(语法错误,意外标记“标识符”)
	for (typename set<T>::const_iterator it = s.begin(); it != s.end(); it++) {
    
    
		cout << *it << " ";
	}
	cout << endl;
}

int main() {
    
    
	//默认无参构造
	set<int> s;

	//插入元素
	s.insert(9);
	s.insert(1);
	s.insert(7);
	s.insert(3);
	s.insert(5);
	printSet(s);	//1 3 5 7 9

	//删除单个元素
	s.erase(s.begin());
	printSet(s);	//3 5 7 9

	//删除指定值
	s.erase(5);
	printSet(s);	//3 7 9

	//清空元素
	s.erase(s.begin(), s.end());
	//s.clear();
	printSet(s);	//(空)

	return 0;
}

5 set查找【find()】和统计【count()】

查找元素
find(key);:查找目标值key是否存在。若存在,则返回该值对应元素的迭代器指向位置;若不存在,则返回结束迭代器 s.end()。

注:成员函数find(key);返回值为迭代器类型

//判断set容器是否存在某元素
int val = 5;

//查找元素,返回迭代器类型
set<int>::iterator pos = s.find(val);
//判断元素是否存在
if(pos != s.end()){
    
    
	cout << "查找到目标值:" << *pos << endl;
}

统计元素个数
count(key);:统计目标值key的元素个数。
set容器:元素不可重复,返回结果为01
multiset容器:元素可重复,返回结果为01n

示例:set查找元素和统计元素个数

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

//查找元素
void func1() {
    
    
	set<int> s;

	//插入元素
	s.insert(9);
	s.insert(1);
	s.insert(7);
	s.insert(3);
	s.insert(5);

	int key = 5;
	//find():查找元素,返回迭代器类型
	set<int>::iterator pos = s.find(key);
	
	//判断元素是否存在
	if (pos != s.end()) {
    
    
		cout << "查找到目标值:" << *pos << endl;
	}else{
    
    
		cout << "未找到目标值:" << endl;
	}
}

//统计元素个数-set容器
void func2() {
    
    
	set<int> s;

	//插入元素
	s.insert(9);
	s.insert(1);
	s.insert(7);
	s.insert(3);
	s.insert(5);
	s.insert(5);
	s.insert(5);

	//set容器:元素不可重复,返回结果为0或1。
	cout << s.count(5) << endl;		//1
}

//统计元素个数-multiset容器
void func3() {
    
    
	multiset<int> s;

	//插入元素
	s.insert(9);
	s.insert(1);
	s.insert(7);
	s.insert(3);
	s.insert(5);
	s.insert(5);
	s.insert(5);

	//multiset容器:元素可重复,返回结果为0、1或n。
	cout << s.count(5) << endl;		//3
}

int main() {
    
    
	//func1();
	//func2();
	func3();

	return 0;
}

6 set和multiset区别

set和multiset的区别
set:不可插入重复数据。
pair<iterator, bool> insert(value_type&& _Val);
set容器insert(elem)函数返回值类型为pair对组pair<iterator, bool>,会返回插入操作的结果,即不可以插入重复元素。

multiset:可插入重复数据。
iterator insert(value_type&& _Val);
multiset容器insert(elem)函数返回值类型为iterator,不会返回插入操作的结果,即可以插入重复元素。

示例

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

//set插入数据
void func1() {
    
    
	set<int> s;

	//pair<iterator, bool> insert(value_type && _Val);
	//set容器的insert()元素返回 对组类型<迭代器类型, 布尔类型>
	pair<set<int>::iterator, bool> pair1 = s.insert(1);	//第1次插入元素1
	if (pair1.second) {
    
    	//第2个参数:布尔类型
		cout << "数据1插入成功.." << endl;
	}
	else {
    
    
		cout << "数据1插入失败.." << endl;
	}

	pair<set<int>::iterator, bool> pair2 = s.insert(1);	//第2次插入元素1
	if (pair2.second) {
    
    	//第2个参数:布尔类型
		cout << "数据1再次插入成功.." << endl;
	}
	else {
    
    
		cout << "数据1再次插入失败.." << endl;
	}

	//数据1插入成功..
	//数据1再次插入失败..
}

//multiset插入数据
void func2() {
    
    
	multiset<int> ms;

	//iterator insert(value_type && _Val);
	//multiset容器的insert()元素返回 迭代器类型
	set<int>::iterator it1 = ms.insert(1);	//第1次插入元素1
	set<int>::iterator it2 = ms.insert(1);	//第2次插入元素1
	
	for (typename set<int>::const_iterator it = ms.begin(); it != ms.end(); it++) {
    
    
		cout << *it << " ";		//1 1(两次插入元素1均成功)
	}
}

void main() {
    
    
	//func1();
	func2();
}

7 pair对组创建

对组:成对出现的数据。使用对组可返回两个数据。

对组的创建方式
(1)有参构造函数:pair<type1, type2> p(value1, value2);
(2)make_pair()函数:pair<type1, type2> p = make_pair(value1, value2);

对组元素的访问方式
成员属性first:返回对组第1个元素的值;
成员属性second:返回对组第2个元素的值。

示例:对组的使用

#include <iostream>
using namespace std;

void main() {
    
    
	//创建对组-有参构造函数
	pair<string, int> p1("Tom", 16);
	cout << p1.first << endl;	//Tom
	cout << p1.second << endl;	//16

	//创建对组-make_pair函数
	pair<string, int> p2 = make_pair("Jerry", 18);
	cout << p2.first << endl;	//Jerry
	cout << p2.second << endl;	//18
}

8 set容器排序【仿函数operator()】

set容器默认升序排序,利用仿函数,通过重载小括号operator()插入元素之前指定排序规则,并在创建set容器对象时,向set容器的类模板参数列表传入指定排序规则。

/* 定义自定义排序规则的仿函数的类 */
//使用类模板增强通用性
template<class T>
class MyCompare {
    
    
public:
	/* 重载仿函数() */
	//第1个小括号:重载小括号运算符
	//第2个小括号:operator()函数的形参列表的小括号
	//必须使用const修饰operator()函数
	//否则编译器报错:const MyCompare的表达式会丢失 const-volatile 限定符
	bool operator()(T val1, T val2) const {
    
    
		return val1 > val2;		//降序排序
		//return val1 < val2;	//升序排序
	}
};

/* 创建set容器对象时,向set容器的类模板参数列表传入指定排序规则MyCompare类型 */
//类模板参数列表需传入类型,使用包含仿函数的MyCompare类型
set<double, MyCompare<double>> s;

注:使用set容器对自定义数据类型排序时,必须指定排序规则。


示例1:set容器对内置数据类型排序

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

/* 定义自定义排序规则的仿函数的类 */
//使用类模板增强通用性
template<class T>
class MyCompare {
    
    
public:
	/* 重载仿函数() */
	//第1个小括号:重载小括号运算符
	//第2个小括号:operator()函数的形参列表的小括号
	//必须使用const修饰operator()函数
	//否则编译器报错:const MyCompare的表达式会丢失 const-volatile 限定符
	bool operator()(T val1, T val2) const {
    
    
		return val1 > val2;		//降序排序
		//return val1 < val2;	//升序排序
	}
};

int main() {
    
    
	//创建set容器对象时,向set容器的类模板参数列表传入指定排序规则MyCompare类型
	//类模板参数列表需传入类型,使用包含仿函数的MyCompare类型
	set<double, MyCompare<double>> s;

	//插入元素
	s.insert(6.6);
	s.insert(3.3);
	s.insert(9.9);
	s.insert(1.1);
	s.insert(7.7);

	//遍历set容器
	for (set<double, MyCompare<double>>::iterator it = s.begin(); it != s.end(); it++) {
    
    
		cout << *it << "  ";		//9.9  7.7  6.6  3.3  1.1
	}
	cout << endl;

	return 0;
}


示例2:set容器对自定义数据类型排序

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

class Student {
    
    
public:
	string name;
	int score;

	Student(string name, int score) {
    
    
		this->name = name;
		this->score = score;
	}
};

/* 定义自定义排序规则的仿函数的类 */
class MyCompare {
    
    
public:
	/* 重载仿函数() */
	//必须使用const修饰operator()函数
	bool operator()(Student s1, Student s2) const {
    
    
		return s1.score > s2.score;		//升排序
		//return s1.score < s2.score;	//降序排序
	}
};

int main() {
    
    
	//创建set容器对象时,向set容器的类模板参数列表传入指定排序规则MyCompare类型
	set<Student, MyCompare> s;

	//插入元素
	Student s1("Jack", 80);
	Student s2("Tom", 100);
	Student s3("Jerry", 60);
	Student s4("Lucy", 90);

	s.insert(s1);
	s.insert(s2);
	s.insert(s3);
	s.insert(s4);

	//遍历set容器
	for (set<Student, MyCompare>::iterator it = s.begin(); it != s.end(); it++) {
    
    
		cout << "姓名:" << (*it).name << ",成绩:" << it->score << endl;
	}
	//姓名:Tom,成绩:100
	//姓名:Lucy,成绩:90
	//姓名:Jack,成绩:80
	//姓名:Jerry,成绩:60

	return 0;
}

猜你喜欢

转载自blog.csdn.net/newson92/article/details/113931023
今日推荐