C++ STL学习:map容器
一、map容器基本知识
1、基本概念:
- map中所有的元素都是pair
- pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
- 所有元素都会根据元素的键值自动排序
- 头文件是
<map>
2、本质:
- map/multimap属于关联式容器,底层结构使用二叉树实现。
3、优点:
- 可以根据key值快速找到value值
- map和multimap的区别:
- map不允许容器中有重复key值元素
- multimap允许容器中有重复key值元素
二、map构造和赋值
两种方式构造:
//map<T1,T2> mp;//默认构造函数
//map(const map &mp);//拷贝构造函数
赋值:
map& operator=(const map &mp);//重载等号操作符
#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; //默认构造
m.insert(pair<int, int>(1, 10));//pair对组
m.insert(pair<int, int>(2, 20));
m.insert(pair<int, int>(3, 30));
printMap(m);
map<int, int>m2(m); //拷贝构造
printMap(m2);
map<int, int>m3;
m3 = m2; //赋值
printMap(m3);
}
int main() {
test01();
system("pause");
return 0;
}
总结:map中所有元素都是成对出现,插入数据时候要使用对组。
三、map大小和交换
函数原型:
- size();//返回容器中元素的数目
- empty();//判断容器是否为空
- swap(st);//交换两个集合容器
#include<iostream>
using namespace std;
#include <map>
//大小
void tset1()
{
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;
}
}
//输出函数
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;
}
}
//交换
void test2()
{
map<int,int>m1;
m1.insert(pair<int,int>(1,10));
m1.insert(pair<int,int>(2,20));
m1.insert(pair<int,int>(3,30));
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(m1); printmap(m1);
cout<<"交换后"<<endl;
m1.swap(m2);//互相交换
printmap(m1); printmap(m1);
}
四、map插入和删除
函数原型:
- insert(elem);//插入元素
- clear();//清除所有元素
- erase(pos);//删除pos迭代器所指的元素,返回下一个元素的迭代器
- erase(beg,end);//删除区间[beg,end]的所有元素,返回下一个元素的迭代器
- erase(key);//删除容器中值为key的元素
#include <iostream>
using namespace std;
#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 test1()
{
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;//最简单但是不建议用于插入(因为容易出错),但可以用于根据key访问value值
//删除
m.erase(m.begin());
printmap(m);
m.erase(3)//按照key来删除
printmap(m)
//等价于m.clear()
m.erase(m.begin(),m.end());
printmap(m);
}
int main()
{
test1();
printmap();
return ;0
}
五、map查找和统计
函数原型:
- find(key) //查找key是都存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
- count(key) //统计key的元素个数(map只能是0或1)
#include<iostream>
using namespace std;
#include <map>
void test1()
{
//查找
map<int,int>m;
m.insert(pair<int,int>(1,10));
m.insert(pair<int,int>(3,30));
m.insert(pair<int,int>(2,20));
map<int,int>::iterator pos = m.find(3);//!!!千万记住返回的是一个迭代器m.find()->->operator pos!!!
if(pos!=m.end())
{
cout<<"查到了元素key"<<(*pos).first<<"value="<<pos->second<<endl;
}
else
{
cout<<"未找到元素"<<endl;
}
//统计
//map不允许插入重复key元素,count统计为0或1
//multimap的count统计可能大于一
int num=m.count(3);
cout<<"num="<<num<<endl;
}
六、map容器排序
- 利用仿函数,可以改变排序规则
#include <iostream>
using mamespace std;
#include <map>
//仿函数。利用仿函数进行排序
class mycompare
{
public:
bool operator()(int v1,int v2)
{
//降序
return v1>v2;
}
}
//排序
void test1()
{
map<int,int,mycompare>m; //!!!没有第三个参数时,默认为升序排序
m.insert(make_pair(1,10));
m.insert(make_pair(2,20));
m.insert(make_pair(3,30));
m.insert(make_pair(4,40));
for(map<int,int,mycompare>m::iterator it=m.begin();it!=m.end(),it++) //这里遍历也要加第三个参数
{
cout<<"key="<<it->first<<"value="<<it->second<<endl;
}
}
int main()
{
test1();
return 0;
}
七、产生随机数
·由于下面的例子要用到随机数,所以先熟悉一下随机数的产生
·C++中没有自带的random函数,要实现随机数的生成就需要使用rand()和srand()。
·不过,由于rand()的内部实现是用线性同余法做的,所以生成的并不是真正的随机数,而是在一定范围内可看为随机的伪随机数。
·rand()会返回一随机数值, 范围在0至RAND_MAX 间。RAND_MAX定义在stdlib.h, 其值为2147483647。因为没有随机种子所以,每次运行结果都一样,因此要是有srand()
·srand()可用来设置rand()产生随机数时的随机数种子。通过设置不同的种子,我们可以获取不同的随机数序列。
·可以利用srand((int)(time(NULL))的方法,利用系统时钟,产生不同的随机数种子。不过要调用time(),需要加入头文件< ctime >。
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main()
{
srand((int)time(0)); // 产生随机种子 把0换成NULL也行
for (int i = 0; i < 10; i++)
{
cout << rand()%100<< " ";
}
return 0;
}
产生一定范围随机数的通用表示公式是:
要取得[0,n) 就是rand()%n 表示 从0到n-1的数
要取得[a,b)的随机整数,使用(rand() % (b-a))+ a;
要取得[a,b]的随机整数,使用(rand() % (b-a+1))+ a;
要取得(a,b]的随机整数,使用(rand() % (b-a))+ a + 1;
通用公式:a + rand() % n;其中的a是起始值,n是整数的范围。
要取得a到b之间的随机整数,另一种表示:a + (int)b * rand() / (RAND_MAX + 1)。 可以用宏定义表示:#define random(a,b) (rand()%(b-a)+a)
要取得0~1之间的浮点数,可以使用rand() / double(RAND_MAX)。
参考:https://www.cnblogs.com/xiaokang01/p/9786751.html
八、案例:员工分组
要求:
- 公司今天招聘了10个员工(ABCDEFGHIJ),10名员工进入公司之后,需要指派员工在那个部门工作
- 员工信息有: 姓名 工资组成;部门分为:策划、美术、研发
- 随机给10名员工分配部门和工资
- 通过multimap进行信息的插入 key(部门编号) value(员工)
- 分部门显示员工信息
步骤: - 创建10名员工,放到vector中
- 遍历vector容器,取出每个员工,进行随机分组
- 分组后,将员工部门编号作为key,具体员工作为value,放入到multimap容器中
- 分部门显示员工信息
#include<iostream>
#include<vector>
#include<string>
#include<map>
#include<ctime>
using namespace std;
//!!!!!!!!!!!!!!!!来个宏定义!!!!!!!!!!!!!!有点忘了,要记住,重新熟悉
#define cehua 0
#define meishu 1
#define yanfa 2
class worker
{
public:
string name;
int salary;
};
//随机创建员工
void createworker(vector<worker>&v)
{
string nameseed="ABCDEFGHIJ";
for(int i=0;i<10;i++)
{
worker worker;
worker.name="员工";
worker.name+=nameseed[i];
worker.salary=rand()%10000+10000;//10000-19999的随机数,必须加上srand((unsigned int)time(NULL))才会产生不一样的随机数,后面有加!!!!!!!!!!!!!!
//将员工放入容器中
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; //0-2
//将员工插入到分组中
//key部门编号,value具体员工
m.insert(make_pair(depid,*it))
}
}
void showworkerbygroup(multimap<int,worker>&m)
{
cout<<"策划部门"<<endl;
multimap<int,worker>::iterator pos=m.find(cehua);
int count=m.count(cehua); //统计具体人数
in index=0;
for(;pos!m.end()&&index<count;pos++,index++)
{
cout<<"姓名:"<<pos->second.name<<"工资:"<<pos->second.salary<<endl;
}
cout<<"============================================================"<<endl;
cout<<"美术部门"<<endl;
multimap<int,worker>::iterator pos=m.find(meishu);
int count=m.count(meishu); //统计具体人数
in index=0;
for(;pos!m.end()&&index<count;pos++,index++)
{
cout<<"姓名:"<<pos->second.name<<"工资:"<<pos->second.salary<<endl;
}
cout<<"=============================================================="<<endl;
cout<<"研发部门"<<endl;
multimap<int,worker>::iterator pos=m.find(yanfa);
int count=m.count(yanfa); //统计具体人数
in index=0;
for(;pos!m.end()&&index<count;pos++,index++)
{
cout<<"姓名:"<<pos->second.name<<"工资:"<<pos->second.salary<<endl;
}
}
int main()
{
srand((unsigned int)time(NULL));//!!!!!!!!每次产生不一样的随机数!!!!!!!!!!
//1
vector<worker> vworker;
creatworker(vworker);
//2
multimap<int,worker>mworker;
setgroup(vworker,mworker);
//3
showworkerbygroup(mworker);
system("pause");
return 0;
}