C++ set/multiset 容器

C++ set/multiset 容器


文章目录

  • C++ set/multiset 容器
  • 前言
    • 1. set 基本概念
    • 2. set 构造和赋值
    • 3. set 大小和交换
    • 4. set 插入和删除
    • 5. set 查找和统计
    • 6. set和multiset区别
    • 7. pair 对组创建
    • 8. set 容器排序
  • 总结


前言

本文包含set基本概念、set构造和赋值、set大小和交换、set插入和删除、set查找和统计、set和multiset区别、pair对组创建、set容量排序。


1. set 基本概念

简介:

所有元素都会在插入时自动被排序

本质:

set/multiset属于关联式容器,底层结构是用二叉树实现

set和multiset区别

(1)、set不允许容器中有重复的元素

(2)、multiset允许容器中有重复的元素

2. set 构造和赋值

功能描述:

创建set容器以及赋值

构造:

(1)、set st; 默认构造函数

(2)、set(const set &st); 拷贝构造函数

赋值:

set& operator=(const set &st); 重载等号操作符

// set关联式容器构造和赋值

#include   // 包含标准输入输出流头文件
using namespace std;  // 使用标准命名空间

#include   // 使用set栈容器,需包含头文件set

// const对此容器只是只读,不可以修改
void Fun_Print(const set<int>& s) {   // 使用引用方式&,传入set类型的形参s

	// const_iterator只读迭代器;iterator普通迭代器
	for (set<int>::const_iterator it = s.begin(); it != s.end(); it++) {

		//*it= 100;  // 报错,容器中数据不可修改:表达式必须是可修改的左值

		cout << *it << " ";  // it是个迭代器类型,本是是个指针,需使用*解引用
	}
	cout << endl;
}

void test() {

	// 1、默认构造,无参构造
	set<int> s;

	// 插入数据,只有insert方式
	s.insert(10);
	s.insert(40);
	s.insert(70);

	// set关联式容器特点:1、所有元素插入时候自动被排序;2、set关联式容器不允许插入重复值
	Fun_Print(s);  // Fun_Print()遍历容器

	// 2、拷贝构造函数
	set<int> s1(s);

	Fun_Print(s1);

	// 3、赋值,重构operator=
	set<int> s2;
	s2 = s;

	Fun_Print(s2);
}

int main() {

	test();

	system("pause");  // 相当于在本地 Windows 调试器中的:请按任意键继续...;暂停,方便看清楚输出结果

	return 0;  // 程序正常退出
}

C++ set/multiset 容器_第1张图片

3. set 大小和交换

功能描述:

统计set容器大小以及交换set容器

函数原型:

(1)、empty(); 判断容器是否为空

(2)、size(); 返回容器中元素的数目

(3)、swap(st); 交换两个集合容器

// set关联式容器大小和交换

#include   // 包含标准输入输出流头文件
using namespace std;  // 使用标准命名空间

#include   // 使用set栈容器,需包含头文件set

// const对此容器只是只读,不可以修改
void Fun_Print(const set<int>& s) {   // 使用引用方式&,传入set类型的形参s

	// const_iterator只读迭代器;iterator普通迭代器
	for (set<int>::const_iterator it = s.begin(); it != s.end(); it++) {

		//*it= 100;  // 报错,容器中数据不可修改:表达式必须是可修改的左值

		cout << *it << " ";  // it是个迭代器类型,本是是个指针,需使用*解引用
	}
	cout << endl;
}

void test() {

	// 创建set容器对象,并且通过模板参数指定容器中存放的数据的类型
	set<int> s;
	set<int> s1;

	// 插入数据,只有insert方式
	s.insert(10);
	s.insert(40);
	s.insert(70);
	s1.insert(300);
	s1.insert(200);
	s1.insert(800);

	Fun_Print(s);  // 10 40 70
	Fun_Print(s1);  // 300 200 800

	// 1、empty()判断容器是否为空,为空返回真
	if (s.empty()) {
		cout << "s容器为空!" << endl;
	}
	else {
		cout << "s容器不为空!" << endl;

		// 2、size()返回容器的个数
		cout << "s容器的个数为:" << s.size() << endl;  // 3
	}

	// 3、swap()交换两个容器中的数据元素
	s1.swap(s);

	Fun_Print(s);  // 300 200 800
	Fun_Print(s1);  // 10 40 70
}

int main() {

	test();

	system("pause");  // 相当于在本地 Windows 调试器中的:请按任意键继续...;暂停,方便看清楚输出结果

	return 0;  // 程序正常退出
}

C++ set/multiset 容器_第2张图片

4. set 插入和删除

功能描述:

set容器进行插入数据和删除数据

函数原型:

(1)、insert(elem); 在容器中插入元素

(2)、erase(pos); 删除pos迭代器所指的元素,返回下一个元素的迭代器

(3)、erase(elem); 删除容器中值为elem的元素

(4)、erase(beg, end); 删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器

(5)、clear(); 清除所有元素

// set关联式容器插入和删除

#include   // 包含标准输入输出流头文件
using namespace std;  // 使用标准命名空间

#include   // 使用set栈容器,需包含头文件set

// const对此容器只是只读,不可以修改
void Fun_Print(const set<int>& s) {   // 使用引用方式&,传入set类型的形参s

	// const_iterator只读迭代器;iterator普通迭代器
	for (set<int>::const_iterator it = s.begin(); it != s.end(); it++) {

		//*it= 100;  // 报错,容器中数据不可修改:表达式必须是可修改的左值

		cout << *it << " ";  // it是个迭代器类型,本是是个指针,需使用*解引用
	}
	cout << endl;
}

void test() {

	// 创建set容器对象,并且通过模板参数指定容器中存放的数据的类型
	set<int> s;

	// 1、insert()在容器中插入数据;set容器默认排序规则为从小到大
	s.insert(10);
	s.insert(40);
	s.insert(70);
	s.insert(50);
	s.insert(80);

	Fun_Print(s);  // 10 40 50 70 80

	// 2、erase()删除s容器开始迭代器处的数据元素
	s.erase(s.begin());
	Fun_Print(s);  // 40 50 70 80

	// 3、erase()删除s容器中值为50的数据元素
	s.erase(50);
	Fun_Print(s);  // 40 70 80

	// 4、erase()删除s容器开始迭代器到结束迭代器中的数据元素
	s.erase(s.begin(), s.end());
	Fun_Print(s);  //

	// 5、clear()清空容器中所有的数据元素
	s.clear();
	Fun_Print(s);  //
}

int main() {

	test();

	system("pause");  // 相当于在本地 Windows 调试器中的:请按任意键继续...;暂停,方便看清楚输出结果

	return 0;  // 程序正常退出
}

C++ set/multiset 容器_第3张图片

5. set 查找和统计

功能描述:

对set容器进行查找数据以及统计数据

函数原型:

(1)、find(key); 查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end()

(2)、count(key); 统计key的元素个数 (0或1)

// set关联式容器查找和统计

#include   // 包含标准输入输出流头文件
using namespace std;  // 使用标准命名空间

#include   // 使用set栈容器,需包含头文件set

// const对此容器只是只读,不可以修改
void Fun_Print(const set<int>& s) {   // 使用引用方式&,传入set类型的形参s

	// const_iterator只读迭代器;iterator普通迭代器
	for (set<int>::const_iterator it = s.begin(); it != s.end(); it++) {

		//*it= 100;  // 报错,容器中数据不可修改:表达式必须是可修改的左值

		cout << *it << " ";  // it是个迭代器类型,本是是个指针,需使用*解引用
	}
	cout << endl;
}

void test() {

	// 创建set容器对象,并且通过模板参数指定容器中存放的数据的类型
	set<int> s;

	// 在容器中插入数据;set容器默认排序规则为从小到大
	s.insert(10);
	s.insert(40);
	s.insert(70);
	s.insert(50);
	s.insert(80);

	// 1、find()查找s容器是否存在“50”这个数据元素
	set<int>::iterator pos = s.find(50);  // 返回迭代器,使用set::iterator迭代器pos进行接收

	if (pos == s.end()) {
		cout << "未找到元素" << endl;
	}
	else {
		cout << "找到了元素 : " << *pos << endl;  // 找到了元素 : 50;使用*解出这个迭代器的值
	}

	// 2、count()统计s容器中“50”数据元素的个数
	int num = s.count(50);
	cout << "num = " << num << endl;  // num = 1
}

int main() {

	test();

	system("pause");  // 相当于在本地 Windows 调试器中的:请按任意键继续...;暂停,方便看清楚输出结果

	return 0;  // 程序正常退出
}

在这里插入图片描述

6. set和multiset区别

学习目标:

掌握set和multiset的区别

区别:

(1)、set插入数据的同时会返回插入结果,表示插入是否成功

(2)、set不可以插入重复数据,而multiset可以

(3)、multiset不会检测数据,因此可以插入重复数据

// set关联式容器和multiset关联式容器区别

#include   // 包含标准输入输出流头文件
using namespace std;  // 使用标准命名空间

#include   // 使用set栈容器,需包含头文件set

void test() {

	// 创建set容器对象,并且通过模板参数指定容器中存放的数据的类型
	set<int> s;

	// 1、set插入数据的同时会返回插入结果,表示插入是否成功;返回pair对组
	pair<set<int>::iterator, bool>  res = s.insert(10);  // pair对组,成对出现的一组数据;set::iterator代表插入元素的位置;bool代表插入成功还是失败
	if (res.second) {  // res.second取res的second第二个数据(bool值)
		cout << "第一次插入成功!" << endl;  // 第一次插入成功!
	}
	else {
		cout << "第一次插入失败!" << endl;
	}

	// 2、set不可以插入重复数据,插入重复的10
	res = s.insert(10);
	if (res.second) {
		cout << "第二次插入成功!" << endl;
	}
	else {
		cout << "第二次插入失败!" << endl;  // 第二次插入失败!
	}

	// 创建multiset容器对象,并且通过模板参数指定容器中存放的数据的类型
	multiset<int> ms;

	// 3、multiset不会检测数据,因此可以插入重复数据
	ms.insert(10);
	ms.insert(10);  // 允许插入重复值

	for (multiset<int>::iterator it = ms.begin(); it != ms.end(); it++) {
		cout << *it << " ";  // 10 10
	}
	cout << endl;
}

int main() {

	test();

	system("pause");  // 相当于在本地 Windows 调试器中的:请按任意键继续...;暂停,方便看清楚输出结果

	return 0;  // 程序正常退出
}

C++ set/multiset 容器_第4张图片

7. pair 对组创建

功能描述:

成对出现的数据,利用对组可以返回两个数据

两种创建方式:

(1)、pair p ( value1, value2 );

(2)、pair p = make_pair( value1, value2 );

// pair对组创建

#include   // 包含标准输入输出流头文件
using namespace std;  // 使用标准命名空间

void test() {

	// 1、pair p ( value1, value2 )
	pair<string, int> p(string("张三"), 18);
	cout << "姓名: " << p.first << " 年龄: " << p.second << endl;

	// 2、pair p = make_pair( value1, value2 )
	pair<string, int> p2 = make_pair("李四", 40);
	cout << "姓名: " << p2.first << " 年龄: " << p2.second << endl;
}

int main() {

	test();

	system("pause");  // 相当于在本地 Windows 调试器中的:请按任意键继续...;暂停,方便看清楚输出结果

	return 0;  // 程序正常退出
}

在这里插入图片描述

8. set 容器排序

学习目标:

set容器默认排序规则为从小到大,掌握如何改变排序规则

主要技术点:

利用仿函数,可以改变排序规则 仿函数:重载了函数调用运算符“()”

示例一 set存放内置数据类型

// set关联式容器排序:内置数据类型

#include   // 包含标准输入输出流头文件
using namespace std;  // 使用标准命名空间

#include   // 使用set栈容器,需包含头文件set

// Fun_Compare仿函数,指定排序类型,从小到大
class Fun_Compare
{

public:

	bool operator()(int v1, int v2) const {  // 重载(),返回bool,底层还是需要对两个数进行判断对比
		return v1 > v2;
	}
};

void test() {

	// 创建set容器对象,并且通过模板参数指定容器中存放的数据的类型
	set<int> s;

	// 在容器中插入数据;set容器默认排序规则为从小到大
	s.insert(10);
	s.insert(40);
	s.insert(70);
	s.insert(50);
	s.insert(80);

	// 默认从小到大
	for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
		cout << *it << " ";  // 10 20 30 40 50
	}
	cout << endl;

	// 指定排序规则:从大到小
	// Fun_Compare类型,<>模板内都得放数据类型;仿函数Fun_Compare本质上是一个类型;会按照仿函数Fun_Compare的排序规则进行排序
	set<int, Fun_Compare> s1;  // 插入时就按从小到大给排序好了;如要修改排序规则,不能再插入后指定排序规则;而是要在指定容器时,就指定排序规则,插入前指定
	s1.insert(10);
	s1.insert(40);
	s1.insert(70);
	s1.insert(50);
	s1.insert(80);

	// 遍历set关联式容器
	for (set<int, Fun_Compare>::iterator it = s1.begin(); it != s1.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}

int main() {

	test();

	system("pause");  // 相当于在本地 Windows 调试器中的:请按任意键继续...;暂停,方便看清楚输出结果

	return 0;  // 程序正常退出
}

在这里插入图片描述
示例二 set存放自定义数据类型

// set关联式容器排序:自定义数据类型

#include   // 包含标准输入输出流头文件
using namespace std;  // 使用标准命名空间

#include   // 使用set栈容器,需包含头文件set

// 创建一个Person类
class Person
{

public:

	Person(string name, int age)  // 构造函数,初始值
	{
		this->m_Name = name;
		this->m_Age = age;
	}

	string m_Name;  // 姓名
	int m_Age;  // 年龄
};

// Fun_Compare仿函数,指定排序类型,从小到大
class Fun_Compare
{

public:

	//bool operator()(const Person& p1, const Person &p2) const  // const限定,不可修改;使用引号&,防止拷贝构造(浅拷贝)
	bool operator()(const Person& p1, const Person& p2) const  // const限定,不可修改;使用引号&,防止拷贝构造(浅拷贝)
	{
		// 按照年龄进行排序  降序
		return p1.m_Age > p2.m_Age;
	}
};

void test() {

	// 创建set容器对象,并且通过模板参数指定容器中存放的数据的类型
	set<Person, Fun_Compare> s;  // 指定排序顺序

	Person p1("张三", 18);
	Person p2("李四", 40);
	Person p3("王五", 55);
	Person p4("赵六", 66);

	// 在容器中插入数据
	s.insert(p1);  // 如果未自定义排序规则Fun_Compare,会报错,编译器插入数据时不知道如何进行从小到大排序
	s.insert(p2);
	s.insert(p3);
	s.insert(p4);

	// 遍历set关联式容器
	for (set<Person, Fun_Compare>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << "姓名: " << it->m_Name << " 年龄: " << it->m_Age << endl;
	}
}

int main() {

	test();

	system("pause");  // 相当于在本地 Windows 调试器中的:请按任意键继续...;暂停,方便看清楚输出结果

	return 0;  // 程序正常退出
}

C++ set/multiset 容器_第5张图片


总结

(1)、set 容器插入数据时用insert;

(2)、set 容器插入数据的数据会自动排序;

(3)、set 统计大小 — size;

(4)、set 判断是否为空 — empty;

(5)、set 交换容器 — swap;

(6)、set 插入 — insert;

(7)、set 删除 — erase;

(8)、set 清空 — clear;

(9)、set 查找 — find (返回的是迭代器);

(10)、set 统计 — count (对于set,结果为0或者1);

(11)、如果不允许插入重复数据可以利用set;

(12)、如果需要插入重复数据利用multiset;

(13)、两种方式都可以创建对组,记住一种即可;

(14)、利用仿函数可以指定set容器的排序规则;

(15)、对于自定义数据类型,set必须指定排序规则才可以插入数据。

你可能感兴趣的:(C++,c++,开发语言)