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插入和删除
![](https://i-blog.csdnimg.cn/blog_migrate/eed85278c50c2920b3d307d893078d86.png)
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;
}