栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++ 提高篇 6 之 set、map 容器

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++ 提高篇 6 之 set、map 容器

C++ 自学
  • set 容器
    • set 构造和赋值
    • set 大小和交换
    • set 插入和删除
    • set 查找和统计
    • pair 对组的使用
    • set 和 multiset 的区别
    • set 排序
  • map 容器
    • map 构造和赋值
    • map 大小和交换
    • map 插入和删除
    • map 查找和统计
    • map 排序
  • STL 案例 -- 员工分组

set 容器

特点

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

本质

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

set 和 multiset 的区别

  1. set 不允许容器中有重复的元素
  2. multiset 允许容器中有重复的元素
set 构造和赋值

函数原型

1. 构造函数

  1. set s; // 默认构造函数
  2. set s1(const set &s); // 拷贝构造函数

2. 赋值函数

  1. set& operator=(const set &s); // 重载赋值运算符
#include 
using namespace std;
#include 

// 打印 set 容器内元素
void PrintSet(set &s) {
	for (set::iterator it = s.begin(); it != s.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}

int main() {

	// 1. 构造函数 
	set s;
	// 插入数据 -- set 容器只 insert 方式插入数据
	s.insert(1);
	s.insert(7);
	s.insert(4);
	// 打印容器内元素
	PrintSet(s); // 1 4 7

	// 2. 拷贝构造函数
	set s1(s);
	PrintSet(s1); // 1 4 7

	// 3. 赋值操作
	set s2; // 构造函数
	s2 = s1;
	PrintSet(s2); // 1 4 7

	system("pause");
	return 0;
}
set 大小和交换

函数原型

  1. empty(); // 判断容器是否为空
  2. size(); // 返回容器大小
  3. s.swap(s1); // 将容器 s1 和容器 s 中的元素互换
#include 
using namespace std;
#include 

// 打印 set 容器内元素
void PrintSet(set &s) {
	for (set::iterator it = s.begin(); it != s.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}

int main() {

	// 构造函数 
	set s;

	// 1. 判断容器是否为空
	if (s.empty()) {
		cout << "容器为空!" << endl;
	}

	// 插入数据 -- set 容器只 insert 方式插入数据
	s.insert(1);
	s.insert(7);
	s.insert(4);

	// 2. 打印容器大小
	cout << "容器大小为:" << s.size() << endl;

	// 3. 交换二个不同的容器
	// 准备容器 s1
	set s1;
	s1.insert(6);
	s1.insert(1);
	s1.insert(9);
	// 分别打印二个容器
	PrintSet(s); // 1 4 7
	PrintSet(s1); // 1 6 9
	// 交换
	s1.swap(s);
	// 重新分别打印二个容器
	PrintSet(s); // 1 6 9
	PrintSet(s1); // 1 4 7
	
	system("pause");
	return 0;
}
set 插入和删除

函数原型

  1. insert(elem); // 在容器中插入元素
  2. erase(const_iterator pos); // 删除迭代器指向位置 pos 的元素,返回下一个元素的迭代器
  3. erase(const_iterator start, const_iterator end); // 删除迭代器指向某区间的元素,返回下一个元素的迭代器
  4. erase(elem); // 删除容器中值为 elem 的元素
  5. clear(); // 清空容器
#include 
using namespace std;
#include 

// 打印 set 容器内元素
void PrintSet(set &s) {
	for (set::iterator it = s.begin(); it != s.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}

int main() {

	// 构造函数 
	set s;

	// 1. 插入数据
	s.insert(1);
	s.insert(7);
	s.insert(4);
	s.insert(9);
	s.insert(2);
	PrintSet(s); // 1 2 4 7 9

	// 2. 删除迭代器指向位置 pos 的元素
	s.erase(++s.begin());
	PrintSet(s); // 1 4 7 9

	// 3. 删除迭代器指向区间的元素
	s.erase(++s.begin(), --s.end());
	PrintSet(s); // 1 9

	// 4. 删除容器中值为 elem 的元素
	s.erase(1);
	PrintSet(s); // 9

	// 5. 清空容器
	s.clear();
	PrintSet(s); // 空

	system("pause");
	return 0;
}
set 查找和统计

函数原型

  1. find(elem); // 查找元素 elem 是否存在,存在则返回该元素的迭代器,否则返回 set.end();
  2. count(elem); // 统计元素 elem 的个数
#include 
using namespace std;
#include 

// 打印 set 容器内元素
void PrintSet(set &s) {
	for (set::iterator it = s.begin(); it != s.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}

int main() {

	// 构造函数 
	set s;
	// 插入数据
	s.insert(1);
	s.insert(7);
	s.insert(4);
	s.insert(9);
	s.insert(2);
	PrintSet(s); // 1 2 4 7 9

	set::iterator it = s.find(9);
	// 1. 查找元素是否存在
	if (it != s.end()) {
		cout << "元素存在:" << *it << endl; // 元素存在:9
	}
	else {
		cout << "元素不存在" << endl;
	}

	// 2. 统计元素的个数 -- 元素统计的结果只会出现 0 或 1;因为 set 容器中不允许出现重复元素
	cout << s.count(1) << endl; // 1
	cout << s.count(100) << endl; // 0

	system("pause");
	return 0;
}
pair 对组的使用

功能

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

二种创建方式

  1. pair p(value1, value2);
  2. pair p = make_pair(value1, value2);
#include 
using namespace std;
#include 

int main() {

	// 1. 第一种方式
	pair p("Su", 19);
	// 取数据,p.first 和 p.second 分别为第一个和第二个元素
	cout << "姓名:" << p.first << " 年龄:" << p.second << endl; // 姓名:Su 年龄:19

	// 2. 第二种方式
	pair p1 = make_pair("Mei", 19);
	cout << "姓名:" << p1.first << " 年龄:" << p1.second << endl; // 姓名:Mei 年龄:19

	system("pause");
	return 0;
}
set 和 multiset 的区别

区别

  1. set 不可以重复插入数据,而 multiset 可以
  2. set 插入的时候会返回插入的结果,表示插入是否成功
  3. multiset 不会检测插入的结果,因此可以插入重复的数据
#include 
using namespace std;
#include 

// 打印 set 容器内元素
void PrintSet(set &s) {
	for (set::iterator it = s.begin(); it != s.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}

int index = 0;
void Check(pair::iterator, bool> &ret) {
	index++;
	if (ret.second) {
		cout << "第 " << index << " 次插入成功!" << endl;
	}
	else {
		cout << "第 " << index << " 次插入失败~" << endl;
	}
}

int main() {

	// 构造函数 
	set s;

	// 1. set 容器不允许插入重复值
	// 测试第一次插入 1
	pair::iterator, bool> ret = s.insert(1);
	Check(ret); // 第 1 次插入成功!
	// 测试第二次插入 1
	ret = s.insert(1);
	Check(ret); // 第 2 次插入失败~

	// 2. multiset 容器允许插入重复值
	multiset ms;
	ms.insert(1);
	ms.insert(1);
	ms.insert(1);
	// 打印元素
	for (multiset::iterator it = ms.begin(); it != ms.end(); it++) {
		cout << *it << " "; // 1 1 1
	}
	cout << endl; 

	system("pause");
	return 0;
}
set 排序

1. 内置数据类型

#include 
using namespace std;
#include 

// 打印 set 容器内元素
void PrintSet(set &s) {
	for (set::iterator it = s.begin(); it != s.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}

// 为自定义排序后的容器 set 实现打印函数
void PrintSet1(set &s) {
	for (set::iterator it = s.begin(); it != s.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}

class MyCompare {
public:
	// 重载仿函数
	bool operator()(int num1, int num2) {
		return num1 > num2;
	}
};

int main() {

	set s;
	s.insert(3);
	s.insert(1);
	s.insert(2);
	s.insert(7);
	// 默认排序 -- 升序
	PrintSet(s); // 1 2 3 7

	// 要求实现:降序
	set s1;
	s1.insert(3);
	s1.insert(1);
	s1.insert(2);
	s1.insert(7);
	PrintSet1(s1); // 7 3 2 1

	system("pause");
	return 0;
}

2. 自定义数据类型

#include 
using namespace std;
#include 
#include 

class Person {
public:
	Person(string name, int age) {
		this->Name_ = name;
		this->Age_ = age;
	}

	string Name_;
	int Age_;
};

class MyCompare {
public:
	// 重载仿函数
	bool operator()(const Person &p1, const Person &p2) {
		return p1.Age_ < p2.Age_;
	}
};

// 为自定义排序后的容器 set 实现打印函数
void PrintSet(set &s) {
	for (set::iterator it = s.begin(); it != s.end(); it++) {
		cout << "姓名:" << (*it).Name_ << " 年龄:" << (*it).Age_ << endl;
	}
}

int main() {

	// 自定义排序容器 -- 年龄升序
	set s;
	// 创建数据
	Person p1("Su", 19);
	Person p2("Ku", 39);
	Person p3("Iu", 29);
	Person p4("Pu", 49);
	// 插入数据
	s.insert(p1);
	s.insert(p2);
	s.insert(p3);
	s.insert(p4);

	// 输出容器内元素
	PrintSet(s);
	// outputs:姓名:Su 年龄:19
	//		   姓名:Iu 年龄:29
	//		   姓名:Ku 年龄:39
	//		   姓名:Pu 年龄:49

	system("pause");
	return 0;
}

3. 报错代码

#include 
using namespace std;
#include 
#include 

class Person {
public:
	Person(string name, int age) {
		this->Name_ = name;
		this->Age_ = age;
	}
	int getAge() {
		return Age_;
	}
	string getName() {
		return Name_;
	}
private:
	string Name_;
	int Age_;
};

class MyCompare {
public:
	// 重载仿函数
	bool operator()(const Person &p1, const Person &p2) {
		return (p1.getAge() < p2.getAge());
	}
};

// 为自定义排序后的容器 set 实现打印函数
void PrintSet(set &s) {
	for (set::iterator it = s.begin(); it != s.end(); it++) {
		cout << "姓名:" << (*it).getName() << " 年龄:" << (*it).getAge() << endl;
	}
	cout << endl;
}

int main() {

	// 自定义排序容器 -- 年龄升序
	set s;
	// 创建数据
	Person p1("Su", 19);
	Person p2("Ku", 39);
	Person p3("Iu", 29);
	Person p4("Pu", 49);
	// 插入数据
	s.insert(p1);
	s.insert(p2);
	s.insert(p3);
	s.insert(p4);

	// 输出容器内元素
	PrintSet(s);

	system("pause");
	return 0;
}
map 容器

概念

  1. map 中所有元素都是 pair 对组
  2. pair 中第一个元素为 key(键值),起到索引作用;第二个元素为 value(实值)
  3. 所有元素都会根据元素的键值自动排序

本质

map/multimap 属于关联式容器,底层结构用二叉树实现

优点

可以根据 key 值快速找到 value 值

map 和 multimap 的区别

  1. map 不允许容器中有重复的 key 元素
  2. multimap 允许容器中有重复的 key 元素
map 构造和赋值

函数原型

1. 构造函数

  1. map m; // map 默认构造函数
  2. map m1(const map &m); // 拷贝构造函数

2. 赋值函数

  1. map& operator=(const map &m); // 重载赋值运算符
#include 
using namespace std;
#include 

void PrintMap(map &m) {
	for (map::iterator it = m.begin(); it != m.end(); it++) {
		cout << "key = " << (*it).first << " value = " << (*it).second << endl;
	}
}

int main() {

	// 1. 构造函数
	map m;
	// 插入数据
	m.insert(pair(1, 10));
	m.insert(pair(2, 20));
	m.insert(pair(3, 30));
	m.insert(pair(4, 40));
	// 打印数据
	PrintMap(m);
	// outputs:key = 1 value = 10
	//		    key = 2 value = 20
	//			key = 3 value = 30
	//			key = 4 value = 40

	// 2. 拷贝构造函数
	map m1(m);
	cout << "----------------------" << endl;
	PrintMap(m1); // 如上

	// 3. 赋值
	map m2;
	m2 = m1;
	cout << "----------------------" << endl;
	PrintMap(m2); // 如上

	system("pause");
	return 0;
}
map 大小和交换

函数原型

  1. empty(); // 判断容器是否为空
  2. size(); // 返回容器的大小
  3. m1.swap(m); // 将容器 m1 和 m 的元素互换
#include 
using namespace std;
#include 

void PrintMap(map &m) {
	for (map::iterator it = m.begin(); it != m.end(); it++) {
		cout << "key = " << (*it).first << " value = " << (*it).second << endl;
	}
}

int main() {

	// 构造函数
	map m;

	// 1. 判断容器 m 是否为空
	if (m.empty()) {
		cout << "容器为空!" << endl;
	}

	// 插入数据
	m.insert(pair(1, 10));
	m.insert(pair(2, 20));
	m.insert(pair(3, 30));
	m.insert(pair(4, 40));
	
	// 2. 输出容器的大小
	cout << "容器大小:" << m.size() << endl; // 容器大小:4

	// 3. 交换二个容器
	// 创建新容器 m1
	map m1;
	// 插入数据
	m1.insert(pair(5, 50));
	m1.insert(pair(6, 60));
	// 交换
	m1.swap(m);
	PrintMap(m);
	// outputs:key = 5 value = 50
	//	       key = 6 value = 60

	system("pause");
	return 0;
}
map 插入和删除

函数原型

  1. insert(elem); // 在容器中插入元素
  2. erase(const_iterator pos); // 删除迭代器指向位置 pos 的元素,返回下一个元素的迭代器
  3. erase(const_iterator start, const_iterator end); // 删除迭代器指向某区间的元素,返回下一个元素的迭代器
  4. erase(key); // 删除容器中键为 key 的元素
  5. clear(); // 清空容器
#include 
using namespace std;
#include 

void PrintMap(map &m) {
	for (map::iterator it = m.begin(); it != m.end(); it++) {
		cout << "key = " << (*it).first << " value = " << (*it).second << ";";
	}
	cout << endl;
}

int main() {

	// 构造函数
	map m;

	// 1. 插入数据
	m.insert(pair(1, 10));
	m.insert(pair(2, 20));
	m.insert(pair(3, 30));
	m.insert(pair(4, 40));
	m.insert(pair(5, 50));
	PrintMap(m); // key = 1 value = 10;key = 2 value = 20;key = 3 value = 30;key = 4 value = 40;key = 5 value = 50;
	
	// 2. 删除迭代器指向位置 pos 对应的元素
	m.erase(m.begin()); // 删除第一组元素
	PrintMap(m); // key = 2 value = 20;key = 3 value = 30;key = 4 value = 40;key = 5 value = 50;

	// 3. 删除迭代器指向区间对应的元素
	m.erase(++m.begin(), --m.end());
	PrintMap(m); // key = 2 value = 20;key = 5 value = 50;

	// 4. 删除容器中键为 key 的一组
	m.erase(2);
	PrintMap(m); // key = 5 value = 50;

	// 5. 清空容器
	m.clear();
	PrintMap(m); // 空

	system("pause");
	return 0;
}
map 查找和统计

函数原型

  1. find(key); // 查找键 key 是否存在,存在则返回该键对应元素的迭代器,否则返回 map.end();
  2. count(key); // 统计元素 key的个数
#include 
using namespace std;
#include 

void PrintMap(map &m) {
	for (map::iterator it = m.begin(); it != m.end(); it++) {
		cout << "key = " << (*it).first << " value = " << (*it).second << ";";
	}
	cout << endl;
}

int main() {

	// 构造函数
	map m;
	// 插入数据
	m.insert(pair(1, 10));
	m.insert(pair(2, 20));
	m.insert(pair(3, 30));
	m.insert(pair(4, 40));
	m.insert(pair(5, 50));

	// 1. 查找键 key 是否存在
	map::iterator it = m.find(1);
	if (it != m.end()) {
		cout << "元素存在,索引为:" << it->first << ",值为:" << it->second << endl; // 元素存在,索引为:1,值为:10
	}
	else {
		cout << "元素不存在!" << endl;
	}

	// 2. 统计键 key 对应的数量
	cout << m.count(3) << endl; // 1
	cout << m.count(300) << endl; // 0
	

	system("pause");
	return 0;
}
map 排序
#include 
using namespace std;
#include 

// 降序
class MyCompare {
public:
	bool operator()(int num1, int num2) {
		return num1 > num2;
	}
};

void PrintMap(map &m) {
	for (map::iterator it = m.begin(); it != m.end(); it++) {
		cout << "key = " << (*it).first << " value = " << (*it).second << ";";
	}
	cout << endl;
}

int main() {

	// 构造函数
	map m;
	// 插入数据
	m.insert(pair(1, 10));
	m.insert(pair(2, 20));
	m.insert(pair(3, 30));
	m.insert(pair(4, 40));
	m.insert(pair(5, 50));

	PrintMap(m); // key = 5 value = 50;key = 4 value = 40;key = 3 value = 30;key = 2 value = 20;key = 1 value = 10;

	system("pause");
	return 0;
}
STL 案例 – 员工分组

案例描述

  1. 公司新招聘的 10 个员工(ABCDEFGHIJ)进入公司后分配到不同部门
  2. 员工信息:姓名、工资;部门分为:策划、美术、研发
  3. 随机给 10 名员工分配部门和工资
  4. 通过 multimap 进行信息的插入(key - 部门编号,value - 员工)
  5. 分部门显示员工信息

实现步骤

  1. 创建 10 名员工,放到 vector 中
  2. 遍历 vector 容器,取出每个员工,进行随机分组
  3. 分组后,将员工编号作为 key,具体员工作为 value,放到 multimap 容器中
  4. 分部门显示员工信息
#include 
using namespace std;
#include 
#include 
#include 
#include 
#define CEHUA 0
#define MEISHU 1
#define YANFA 2

class Worker {
public:
	// 设置名字
	void setName(string name) {
		this->Name_ = name;
	}
	// 设置薪水
	void setSalary(int salary) {
		this->Salary_ = salary;
	}
	// 取姓名
	string getName() {
		return Name_;
	}
	// 取工资
	int getSalary() {
		return Salary_;
	}
private:
	string Name_;
	int Salary_;
};

void createWorker(vector &v) {
	string NameSeed = "ABCDEFGHIJ";
	for (int i = 0; i < 10; i++) {
		string name = "员工";
		name += NameSeed[i];
		int salary = rand() % 10000 + 10000; // 0 ~ 19999
		// 创建员工并存放到 vector 数组中
		Worker worker;
		worker.setName(name);
		worker.setSalary(salary);
		v.push_back(worker);
	}
}

void setGroup(vector &v, multimap &m) {
	// 遍历 vector 数组
	for (vector::iterator it = v.begin(); it != v.end(); it++) {
		// 创建部门编号
		int Dept = rand() % 3; // 0 1 2
		// 将编号和具体的人员信息存放到 multimap 中
		m.insert(make_pair(Dept, *it));
	}
}

void showWorkerByGroup(multimap &m) {
	// 1. 统计策划人数
	int count = m.count(CEHUA);
	int index = 0;
	// 查找策划人员
	cout << "策划部门人员如下:" << endl;
	multimap::iterator pos = m.find(CEHUA);
	for (; pos != m.end() && index < count; pos++, index++) {
		cout << "姓名:" << pos->second.getName() << " 工资:" << pos->second.getSalary() << endl;
	}
	cout << "------------------------------------" << endl;
	
	// 2. 统计美术人数
	count = m.count(MEISHU);
	index = 0;
	// 查找美术人员
	cout << "美术部门人员如下:" << endl;
	pos = m.find(MEISHU);
	for (; pos != m.end() && index < count; pos++, index++) {
		cout << "姓名:" << pos->second.getName() << " 工资:" << pos->second.getSalary() << endl;
	}
	cout << "------------------------------------" << endl;

	// 3. 统计研发人数
	count = m.count(YANFA);
	index = 0;
	// 查找研发人员
	cout << "研发部门人员如下:" << endl;
	pos = m.find(YANFA);
	for (; pos != m.end() && index < count; pos++, index++) {
		cout << "姓名:" << pos->second.getName() << " 工资:" << pos->second.getSalary() << endl;
	}
}

int main() {

	// 加入随机数种子
	srand((unsigned int)time(NULL));

	// 1. 创建存储员工的容器 vector 数组
	vector v;

	// 2. 创建 10 名员工(工资随机)并放到 vector 数组中
	createWorker(v);

	// 3. 遍历 vector 容器进行随机分组,并将分组后的编号和人员信息存放在 multimap 容器中
	multimap m;
	setGroup(v, m);

	// 4. 分部门显示员工信息
	showWorkerByGroup(m);
	// outpus:策划部门人员如下:
	//		  姓名:员工D 工资:16500
	//		  姓名:员工I 工资:16962
	//		  姓名:员工J 工资:14464
	//		  ------------------------------------
	//		  美术部门人员如下:
	//		  姓名:员工C 工资:16334
	//		  姓名:员工E 工资:19169
	//		  姓名:员工G 工资:11478
	//		  ------------------------------------
	//		  研发部门人员如下:
	//		  姓名:员工A 工资:10041
	//		  姓名:员工B 工资:18467
	//		  姓名:员工F 工资:15724
	//		  姓名:员工H 工资:19358

	system("pause");
	return 0;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/433536.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号