(3)map/multimap容器、函数对象、谓词、内建函数对象(仿函数)

map/multimap容器

高性能、高效率

map基本概念

简介:

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

本质:

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

优点:

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

map和multimap区别:

  • map不允许容器中有重复key值元素
  • multimap允许容器中有重复key值元素

map构造和赋值

构造:

赋值:

#include<map>
void printMap(map<int, int>& m) {
	for (map<int, int>::iterator it = m.begin(); it != m.end(); it++) {
		cout << "key = " << (*it).first << " value = " << it->second << endl;
	}
	cout << endl;
}
void test01() {
	map<int, int>m;//两个数据类型,一个代表key值,一个是value值
	m.insert(pair<int, int>(1, 10));//pair<int, int>(1, 10) 匿名对组
	m.insert(pair<int, int>(3, 30));
	m.insert(pair<int, int>(2, 20));
	m.insert(pair<int, int>(4, 40));
	printMap(m);//依据key值排序
	//  key = 1 value = 10
	//	key = 2 value = 20
	//	key = 3 value = 30
	//	key = 4 value = 40
	//拷贝构造
	map<int, int>m2(m);
	printMap(m2);//同上
	//赋值
	map<int, int>m3;
	m3 = m2;
	printMap(m3);//同上
}

map中所有元素都成对出现,插入数据时要使用对组

map大小和交换

void printMap(map<int, int>& m) {
	for (map<int, int>::iterator it = m.begin(); it != m.end(); it++) {
		cout << "key = " << (*it).first << " value = " << it->second << endl;
	}
	cout << endl;
}
void test01() {
	map<int, int>m;
	m.insert(pair<int, int>(1, 10));
	m.insert(pair<int, int>(2, 20));
	m.insert(pair<int, int>(3, 30));
	if (m.empty()) {
		cout << "m 为空" << endl;
	}
	else {
		cout << "m 不为空" << endl;
		cout << "m 大小:" << m.size() << endl;
	}
	map<int, int>m2;
	m2.insert(pair<int, int>(4, 40));
	m2.insert(pair<int, int>(5, 50));
	m2.insert(pair<int, int>(6, 60));
	cout << "交换前:" << endl;
	printMap(m);
	printMap(m2);
	cout << "交换后:" << endl;
	m.swap(m2);
	printMap(m);
	printMap(m2);
}

map插入和删除

void printMap(map<int, int>& m) {
	for (map<int, int>::iterator it = m.begin(); it != m.end(); it++) {
		cout << "key = " << (*it).first << " value = " << it->second << endl;
	}
	cout << endl;
}
void test01() {
	map<int, int>m;
	//插入
	m.insert(pair<int, int>(1, 10));//第一种方式
	m.insert(make_pair(2, 20));//第二种
	m.insert(map<int,int>::value_type(3,30));//第三种
	m[4] = 40;//第四种
	//cout << m[5] << endl;//系统会创建一个 key值为5,value值为0 的数据
	//所以[]不建议插入,用途 可以利用key访问到value
	//cout << m[3] << endl;//30
	printMap(m);
	//删除
	m.erase(m.begin());//删第一个数据
	printMap(m);
	m.erase(3);//按照key删除
	printMap(m);
	//清空
	//m.erase(m.begin(), m.end());//相当于清空
	m.clear();
	printMap(m);
}

map查找和统计

void test01() {
	map<int, int>m;
	m.insert(pair<int, int>(1, 10));
	m.insert(pair<int, int>(2, 20));
	m.insert(pair<int, int>(3, 30));
	m.insert(pair<int, int>(3, 30));
	map<int, int>::iterator pos = m.find(3);//返回一个迭代器
	if (pos != m.end()) {
		cout << "查找到了元素 key = " << (*pos).first << " value = " << pos->second << endl;
	}
	else {
		cout << "未找到元素" << endl;
	}
	//统计
	//map不允许插入重复key 元素,count统计而言 结果只会是 0 或 1
	//multimap的count统计可能大于1
	int num = m.count(3);
	cout << " num  = " << num << endl;// num  = 1
}

map容器排序

map容器默认排序规则是 按照 key 值 从大到小排序

利用仿函数,改变排序规则

class MyCompare {
public:
	bool operator()(int v1,int v2) const{
		return v1 > v2;//降序
	}
};
void test01() {
	map<int, int, MyCompare>m;
	m.insert(make_pair(1, 10));
	m.insert(make_pair(2, 20));
	m.insert(make_pair(5, 50));
	m.insert(make_pair(3, 30));
	m.insert(make_pair(4, 40));
	for (map<int, int, MyCompare>::iterator it = m.begin(); it != m.end(); it++) {
		cout << "key = " << (*it).first << " value = " << it->second << endl;
	}
}

案例:员工分组

案例描述

  • 公司今天招聘了10个员工( ABC DEF GHIJ ),10名员工进入公司之后,需要指派员工在那个部门工作
  • 员工信息有:姓名工资组成;部门分为:策划、美术、研发
  • 随机给10名员工分配部门和工资
  • 通过multimap进行信息的插入  key(部门编号) value(员工)
  • 分部门显示员工信息

实现步骤

  • 创建10名员工,放到vector中
  • 遍历vector容器,取出每个员工,进行随机分组
  • 分组后,将员工部门编号作为key,具体员工作为value,放入到multimap容器中
  • 分部门显示员工信息
#include<vector>
#include<map>
#include<string>
#include<ctime>
#define CEHUA 0
#define MEISHU 1
#define YANFA 2
class Worker {
public:
	string m_Name;
	int m_Salary;
};
void createWorker(vector<Worker>& v) {
	string nameSeed = "ABCDEFGHIJ";
	for (int i = 0; i < 10; i++) {
		Worker worker;
		worker.m_Name = "员工";
		worker.m_Name += nameSeed[i];
		worker.m_Salary = rand() % 10000 + 10000;//10000~19999
		v.push_back(worker);//将员工放到容器中
	}
}
//员工分组
void setGroup(vector<Worker>& v, multimap<int, Worker>& m) {
	for (vector<Worker>::iterator it = v.begin(); it != v.end(); it++) {
		//产生随机部门编号
		int depId = rand() % 3;
		//将员工插入到分组中
		//key 部门编号  value 具体员工
		m.insert(make_pair(depId, *it));
	}
}
void showWorkerByGourp(multimap<int, Worker>& m) {
	cout << "策划部门:" << endl;
	multimap<int, Worker>::iterator pos = m.find(CEHUA);
	int count = m.count(CEHUA);//统计具体人数
	int index = 0;
	for (; pos != m.end() && index < count; pos++,index++) {
		cout << "姓名:" << pos->second.m_Name << "  工资: " << pos->second.m_Salary << endl;
	}
	cout << "------------------------------" << endl;
	cout << "美术部门:" << endl;
	pos = m.find(MEISHU);
	count = m.count(MEISHU);//统计具体人数
	index = 0;
	for (; pos != m.end() && index < count; pos++, index++) {
		cout << "姓名:" << pos->second.m_Name << "  工资: " << pos->second.m_Salary << endl;
	}
	cout << "------------------------------" << endl;
	cout << "研发部门:" << endl;
	pos = m.find(YANFA);
	count = m.count(YANFA);//统计具体人数
	index = 0;
	for (; pos != m.end() && index < count; pos++, index++) {
		cout << "姓名:" << pos->second.m_Name << "  工资: " << pos->second.m_Salary << endl;
	}
}
int main() {
	srand((unsigned int)time(NULL));
	//创建员工
	vector<Worker>vWorker;
	createWorker(vWorker);
	//员工分组
	multimap<int, Worker>mWorker;
	setGroup(vWorker, mWorker);
	//分组显示员工
	showWorkerByGourp(mWorker);

	测试
	//for (vector<Worker>::iterator it = vWorker.begin(); it != vWorker.end(); it++) {
	//	cout << "姓名:" << it->m_Name << "  工资:" << it->m_Salary << endl;
	//}
	system("pause");
	return 0;
}

STL函数对象

函数对象概念

概念:

  • 重载函数调用操作符的类,其对象常称为函数对象
  • 函数对象使用重载的 () 时,行为类似函数调用,也叫仿函数

本质:

  • 函数对象(仿函数)是一个,不是一个函数

函数对象使用

  • 函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值
  • 函数对象超出普通函数的概念,函数对象可以有自己的状态
  • 函数对象可以作为参数传递
#include<string>
//函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值
class MyAdd {
public:
	int operator()(int v1, int v2) {
		return v1 + v2;
	}
};
void test01() {
	MyAdd myAdd;//myAdd --- 函数对象
	cout << myAdd(10, 10) << endl;// 20
}
//函数对象超出普通函数的概念,函数对象可以有自己的状态
class MyPrint {
public:
	MyPrint() {
		this->count = 0;
	}
	void operator()(string test) {
		cout << test << endl;
		this->count++;
	}
	int count;//内部自己的状态
};
void test02() {
	MyPrint myPrint;
	myPrint("hello world");
	myPrint("hello world");
	myPrint("hello world");
	myPrint("hello world");
	cout << "myPrint 调用次数:" << myPrint.count << endl;//myPrint 调用次数:4
}
//函数对象可以作为参数传递
void doPrint(MyPrint& mp, string test) {
	mp(test);
}
void test03() {
	MyPrint myPrint;
	doPrint(myPrint, "Hello C++");
}

谓词

谓词概念

  • 返回bool类型的仿函数称为谓词
  • 如果operator()接受一个参数,那么叫做—元谓词
  • 如果operator()接受两个参数,那么叫做二元谓词

一元谓词

class GreaterFive {
public:
	bool operator()(int val) {
		return val > 5;
	}
};
void test01() {
	vector<int>v;
	for (int i = 0; i < 10; i++) {
		v.push_back(i);
	}
	//查找容器中 有无大于5的数字
    //GreaterFive() --- 匿名函数对象
	vector<int>::iterator it = find_if(v.begin(), v.end(), GreaterFive());
	if (it == v.end()) {
		cout << " 未找到 " << endl;
	}
	else {
		cout << "找到了大于5的数字:" << *it << endl;//找到了大于5的数字:6
	}
}

二元谓词

class MyCompare {
public:
	bool operator()(int val1,int val2) {
		return val1 > val2;
	}
};
void test01() {
	vector<int>v;
	v.push_back(10);
	v.push_back(40);
	v.push_back(50);
	v.push_back(20);
	v.push_back(30);
	sort(v.begin(), v.end());
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it << " ";//10 20 30 40 50
	}
	cout << endl;
    //使用函数对象,改变算法策略 ,改变排序规则 变为从大到小
	sort(v.begin(), v.end(), MyCompare());
	cout << "--------------------------------" << endl;
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it << " ";//50 40 30 20 10
	}
	cout << endl;
}

内建函数对象

概念

STL内建了一些仿函数

分类

  • 算术仿函数
  • 关系仿函数
  • 逻辑仿函数

用法

  • 这些仿函数所产生的对象,用法和一般函数完全相同
  • 使用内建函数对象,需要引入头文件  #include<functional>
     

算术仿函数

功能

  • 实现四则运算
  • 其中negate 是一元运算,且是取反仿函数

仿函数原型:

#include<functional>
void test01() {
	negate<int>n;//一元 取反
	n(50);
	cout << n(50) << endl;//-50
	plus<int>p;//加法
	cout << p(10, 20) << endl;//30
}

关系仿函数

仿函数原型:

//关系仿函数 greater<> 大于
#include<functional>
//class MyCompare {
//public:
//	bool operator()(int val1,int val2) {
//		return val1 > val2;
//	}
//};
void test01() {
	vector<int>v;
	v.push_back(10);
	v.push_back(40);
	v.push_back(50);
	v.push_back(20);
	v.push_back(30);
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it << " ";//10 40 50 20 30
	}
	cout << endl;
	//sort(v.begin(), v.end(), MyCompare());
	sort(v.begin(), v.end(), greater<int>());//运用内建的仿函数排序
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it << " ";//50 40 30 20 10
	}
	cout << endl;
}

关系仿函数中最常用的是 greater<> 大于

逻辑仿函数

函数原型:

void test01() {
	vector<bool>v;
	v.push_back(true);
	v.push_back(false);
	v.push_back(true);
	v.push_back(false);
	for (vector<bool>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it << " ";//1 0 1 0
	}
	cout << endl;
	//利用逻辑非 将 容器v 搬运到 容器v2中,并执行取反操作
	vector<bool>v2;
	v2.resize(v.size());//提前开辟空间
	transform(v.begin(), v.end(), v2.begin(), logical_not<bool>());
	for (vector<bool>::iterator it = v2.begin(); it != v2.end(); it++) {
		cout << *it << " ";//0 1 0 1
	}
	cout << endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值