用C++刷题很久了,对用到的STL做个总结,方便以后查阅学习。
文章目录
STL的诞生
C++的面向对象和泛型编程思想,目的是复用性的提升。
面向对象三大特性:继承、封装、多态。
STL从广义上分为:容器(container)、算法(algorithm)、迭代器(iterator)
算法和容器之间通过迭代器进行链接。
STL六大组件:容器、算法、迭代器、仿函数、适配器、空间配置器
1 容器 :各种数据结构,vector,list,deque,set,map
2 算法:常见的算法,sort ,find,copy,for_each
3 迭代器:容器和算法之间的连接
4 仿函数:行为类似函数,可作为某些算法的某种策略,例如排序默认升序,可写函数该为降序
5 适配器:用来修饰容器或者仿函数或迭代器接口的东西
6 空间配置器:负责空间的配置和管理
STL中的容器、算法和迭代器
容器:将运用最广泛的数据结构实现出来
常用的数据结构:数组、链表、树、栈和队列、集合
容器又分为:
序列式容器:强调值的排序,容器中每个数据有固定的位置,如vector,list等
关联式容器:二叉树结构,元素之间没有严格的物理上的顺序,如map,set
算法:质变算法和非质变算法
质变算法:运算过程中会更改区间内元素的内容,拷贝,替换等
非质变算法:查找,计数,遍历,查找等
迭代器:容器和算法之间的粘合剂,沟通的桥梁。
提供一种方法,遍历某个容器中的各个元素,又无需暴露该容器的内部表示方式。
每个容器都有自己的专属迭代器。
vector容器
vector和普通数组之间的区别:
数组是静态空间,vector可以动态扩展。
动态扩展并不是在原有空间后续接新的空间,而是找到更大内存卡农关键,然后将原始数据拷贝到新空间,释放原空间。
容器:vector
算法:for_each
迭代器:vector::iterator 。支持随机访问
vector插入数据
vector<int>v;//创建容器,命名为v
v.push_back(1);//插入数据
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
//通过迭代器访问容器中的数据
vector<int>::iterator it = v.begin();//起始迭代器,指向容器中第一个元素
cout << *it << endl;//1
vector<int>::iterator itend = v.end();//结束迭代器,指向容器中最后一个元素的下一个位置
while (it != itend) {
cout << *it << endl;//1,2,3,4,5
it++;
}
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
cout << *it << endl;//1,2,3,4,5
}
for_each(v.begin(), v.end(), myprint);//这种需要自己写一个函数传进去,告诉要干嘛
return 0;
v.insert(v1.begin(),2,1000)//在指定位置插入2个1000
使用迭代器遍历数据的方式有多种,常见的是for循环!
vector也可以存放自定义的数据类型,
如下图代码所示
class person {//定义一个person类
public:
person(string name, int age) {
this->m_name = name;
this->m_age = age;
}
string m_name;
int m_age;
};
int main()
{
vector<person>v;
person p1("aa", 10);
person p2("bb", 20);
person p3("cc", 30);
person p4("dd", 40);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
for (vector<person>::iterator it = v.begin(); it != v.end(); it++) {
cout << it->m_name << " " << (*it).m_age << endl;
}
嵌套vector存放数据,并用迭代器遍历
vector<vector<int>>v;//二维数组
vector<int>v1;
vector<int>v2;
vector<int>v3;
vector<int>v4;
for (int i = 0; i < 4; i++) {
v1.push_back(i + 1);
v2.push_back(i + 2);
v3.push_back(i + 3);
v4.push_back(i + 4);
}
v.push_back(v1);
v.push_back(v2);
v.push_back(v3);
v.push_back(v4);
for (vector<vector<int>>::iterator it = v.begin(); it != v.end(); it++) {
//*it是容器vector《int》因此需要两个循环
for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end(); vit++) {
cout << *vit<<" " ;
}
cout << endl;
}
vector删除元素
1:如果想删除指定位置或者末尾元素,可以采用下面的方式进行删除
vector<int>v1;
for (int i = 0; i < 4; i++) {
v1.push_back(i + 1);
}
for_each(v1.begin(), v1.end(), myptring);
cout << endl;
v1.pop_back();//如果要删除末尾的元素
for_each(v1.begin(), v1.end(), myptring);
cout << endl;
auto it1 = v1.begin() + 2;//可以删除指定位置的元素,但删除之后迭代器会失效
v1.erase(it1);
for_each(v1.begin(), v1.end(), myptring);
2:如果不知道元素的具体位置,可以使用迭代器删除,但是因为删除元素之后迭代器就会失效,因此删除时候不能直接用定义好的迭代器,需要删除元素之后返回新的迭代器。代码如下
vector<int>v1;
for (int i = 0; i < 4; i++) {
v1.push_back(i + 1);//插入元素
}
for_each(v1.begin(), v1.end(), myptring);
cout << endl;
for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++) {
if (*it == 3) {
it = v1.erase(it);//返回新的迭代器,不然会报错
}
else {
it++;
}
}
for_each(v1.begin(), v1.end(),myptring);
vector互换容器
vector<int>v;
for (int i = 0; i < 10; i++) {
v.push_back(i);
}
for_each(v.begin(), v.end(), myptring);//0 1 2 3 4 5 6 7 8 9
cout << endl;
vector<int>v1;
for (int i = 10; i >0; i--) {
v1.push_back(i);
}
for_each(v1.begin(), v1.end(), myptring);//10 9 8 7 6 5 4 3 2 1
cout << endl;
cout << "after the exchange" << endl;
v.swap(v1);
for_each(v.begin(), v.end(), myptring);//10 9 8 7 6 5 4 3 2 1
swap函数主要用来收缩内存
利用匿名对象交换,然后系统回收匿名对象指代的对象内存
vector<int>v;
for (int i = 0; i < 100000; i++) {
v.push_back(i);
}
cout << v.size() << endl;//100000
cout << v.capacity() << endl;//138255
v.resize(4);
cout << v.size() << endl;//4
cout << v.capacity() << endl;//138255
vector<int>(v).swap(v);//匿名函数
cout << v.size() << endl;//4
cout << v.capacity() << endl;//4
vector预留空间
减少vector自动扩充空间扩充的太大,可以手动指定预留多少大小
下图代码看看 10万数据需要扩充多少次,
vector<int>v;
int num=0;
int *p=nullptr;//
for (int i = 0; i < 100000; i++) {
v.push_back(i);
if (p != &v[0]) {
p = &v[0];
num++;
}
}
cout << num << endl;//30
如果预留空间之后,扩充次数就是1
vector<int>v;
v.reserve(100000);
int num=0;
int *p=nullptr;//
for (int i = 0; i < 100000; i++) {
v.push_back(i);
if (p != &v[0]) {
p = &v[0];
num++;
}
}
cout << num << endl;//30
string容器
基本概念
本质:string是C++风格字符串,string本质是一个类
string和char* 的区别:
char*是一个指针
string是一个类,内部封装了char *,管理这个字符串,是一个char *型的容器
特点:
string内部封装了很多成员方法
例如find ,delete,replace,insert
string管理char * 分配的内存,不用担心复制越界或取值越界
构造函数
string();//创建一个空字符串
string(const char* s)//用字符串s初始化
string(const string& str)//引用,使用另一个string对象初始化
string(int n,char c)//使用n个字符c初始化
string s1;
const char*str = "hello world";
string s2(str);
cout << "s2 is: " << s2 << endl;//用str去初始化新的字符串s2
string s3(10, 'a');
cout << s3 << endl;
赋值操作
string s1;
s1 = "kobe bryant";
cout << s1 << endl;
string s2;
s2 = s1;
cout << s2 << endl;
string s3;
s3 = "a";
cout << s3 << endl;;
string s5;
s5.assign("hello ww");
cout << s5 << endl;
string s6;
s6.assign("hello AC++", 5);
cout << s6 << endl;
string拼接操作
string s1 = "我";
s1 += "喜欢湖人队";
cout << s1 << endl;
string s2 = "kobe";
cout << s1 + s2 << endl;
s1.append("喜欢湖人队");
cout << s1 << endl;
s1.append("喜欢湖人队", 3);
cout << s1 << endl;
s1.append(s2);//追加另外一个字符串到当前字符串
cout << s1 << endl;
s1.append(s2, 0, 3);//参数2从哪个位置开始截取,参数3是截取多少个
cout << s1 << endl;
string查找和替换
查找:
主要是find和rfind,返回的是一个int型数据,找不到则返回-1;
//查找
//find从左往右找,rfind从右往左找
string s1 = "abcdefghil";
int pos = s1.find("de");//返回的一个int类型的值,找不到返回-1;
cout << pos << endl;
if (pos == -1)cout << "没找到" << endl;
else cout << "the location is:"<<pos << endl;
int pos1 = s1.rfind("de");//从右往左查找第一个出现的字符串;
cout << pos1 << endl;
替换:
//替换
//
string s1 = "abcdefghil";
s1.replace(1, 3, "kobe");//第一个参数是起始位置,第二个参数截止位置,第三个参数是替换的字符串
cout << s1 << endl;//输出结果为 akobeefghil
string比较
比较按照的是ASCII码值进行比较
相等返回 0;
大于返回 1;
小于返回 -1;
比较是逐次按照对应字母大小;
主要是用来比较两个字符串是否相等。
//字符串比较
string s1 = "kobe";
string s2 = "james";
int res = s1.compare(s2);
cout << res << endl;//输出1
string字符存取
string中单个字符存取方式有两种。
char&operator[](int n);//通过[]方式获取
char&at(int n);//通过at方式获取,越界时候会抛出异常,更安全
string s1 = "kobe the legend";
for (int i = 0; i < s1.size(); i++) {
cout << s1[i] << " " ;
}
cout << endl;
for (int i = 0; i < s1.size(); i++) {
cout << s1.at(i) << " ";//越界时候会抛出异常
}
cout << endl;
s1[0] = 'w';//对字符串进行修改
cout << s1 << endl;
string插入和删除
string s = "hello";
s.insert(1, "kobe");
cout << s << endl;//输出结果为hkobeello
s.erase(1, 4);//第一个参数位置,第二个参数是删几个字符
cout << s << endl;//输出结果为hello
string子串
截取字符串中某一段字符串
string s = "abcdefg";
string subs = s.substr(1, 3);//第一个参数为截取起始位置,第二个参数为截取多少个
cout << subs << endl;//输出结果为bcd
string email = "kobe@qq.com";
//从邮件中获取用户名
int pos = email.find("@");
string name = email.substr(0, pos);
cout << name <<endl;
deque容器
跟vector相比,deque的两端都可以进行删除与删除,vector在头部插入需要移动大量的数据。
deque内部工作原理:
deque内部有个中控器,维护每段缓冲区中的内容,缓冲区存放真实数据。
中控器维护的是每个缓冲区的地址,使得deque使用时像一片连续的内存空间
deque的构造函数
void printd(const deque<int>&d) {//封装一个只读打印数据函数
for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
int main()
{
deque<int>d;
for (int i = 0; i < 10; i++) {//直接赋值构造
d.push_back(i);
}
printd(d);
deque<int>d1(d.begin(), d.end());//区间形式赋值
printd(d1);
deque<int>d2(10, 100);//10个100
printd(d2);
}
deque赋值操作
操作跟vector差不多
deque<int>d;
for (int i = 0; i < 10; i++) {
d.push_back(i);
}
deque<int>d1;
d1 = d;//直接赋值
printd(d1);
deque<int>d2;
d2.assign(d1.begin(), d1.end());//assign赋值
printd(d2);
deque大小操作
deque没有capacity概念,理论上可以无限填充,扩充容量时候默认是0,也可以指定
deque<int>d;
for (int i = 0; i < 10; i++) {
d.push_back(i);
}
cout << d.size() << endl;
d.resize(15);
printd(d);//0 1 2 3 4 5 6 7 8 9 0 0 0 0 0
d.resize(20,1);
printd(d);//0 1 2 3 4 5 6 7 8 9 0 0 0 0 0 1 1 1 1 1
deque插入删除
插入操作
deque<int>d;
d.push_back(10);//尾插
d.push_back(20);
d.push_front(30);
d.push_front(40);//头插
d.pop_back();//尾删
d.pop_front();//头删
//指定位置插入
d.insert(d.begin(), 1000);
d.insert(d.begin()+2, 2000);
printd(d);//1000 30 2000 10
//按照区间进行插入
deque<int>d1;
d1.push_back(1);
d1.push_back(2);
d1.push_back(3);
d.insert(d.begin(), d1.begin(), d1.end());//第一个参数插入位置,第二和第三参数是插入数据区间
printd(d);//1 2 3 1000 30 2000 10
删除操作
删除时候提供的一定得是迭代器,迭代器可以偏移位置,指定位置
deque<int>::iterator it = d.begin();
d.erase(it);//z指定位置
printd(d);//2 3 1000 30 2000 10
d.clear();清空//
deque数据存取
可以通过at或者[]访问元素,
front() back()可以获取deque的头部和尾部的元素
案例 评委打分
class person {//定义选手的类
public:
person(string name, int score) {//两个属性 姓名和分数
this->m_name = name;
this->m_score = score;
}
string m_name;
int m_score;
};
void creatperson(vector<person>&v) {//实例化选手类
string nameseed = "ABCDE";
for (int i = 0; i < 5; i++) {
string name = "选手";
name += nameseed[i];
int score = 0;
person p(name, score);//利用上面给出的name和score 实例化一个person类
v.push_back(p);
}
}
void setscore(vector<person>&v) {//给每个选手打分
for (vector<person>::iterator it = v.begin(); it != v.end(); it++) {
deque<int>d;
for (int i = 0; i < 10; i++) {//先打分
int score = rand() % 41 + 60;
d.push_back(score);
}
cout << it->m_name << " ";
for (deque<int>::iterator it1 = d.begin(); it1 != d.end(); it1++) {
cout << *it1 << " ";
}
cout << endl;
sort(d.begin(), d.end());
d.pop_back();//去除最低分和最高分
d.pop_front();
int av = 0;
for (deque<int>::iterator it1 = d.begin(); it1 != d.end(); it1++) {
av += *it1;
}
int avg = av / d.size();//选手最终的平均分
it->m_score = avg;//将最终的平局分赋值给选手
}
}
void showscore(vector<person>&v) {
cout << "每个选手的最终平均分是 " << endl;
for (vector<person>::iterator it = v.begin(); it != v.end(); it++) {
cout << it->m_score << endl;
}
}
int main()
{
vector<person>v;
creatperson(v);//创建选手类
/*for (vector<person>::iterator it = v.begin(); it != v.end(); it++) {
cout << it->m_name << " " << it->m_score << endl;
}*/
setscore(v);//给每个选手打分
showscore(v);
}
stack容器
栈是一种先进后出(FILO)的数据结构,只有一个出口,只能从栈顶进出数据。
栈不允许进行遍历。
stack常用操作
stack<int>s;
s.push(1);
s.push(2);
s.push(3);
s.push(4);
cout << s.top() << endl;
s.pop();
cout << s.top() << endl;
cout << s.empty() << endl;
queue容器
queue是一种先进先出的数据结构。
queue<int>q;
q.push(1);
q.push(2);
q.push(3);
q.push(4);
cout << q.front() << endl;
cout << q.back() << endl;
q.pop();
cout << q.front() << endl;
list容器
将数据进行链式存储
链表(list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的
链表的组成:一个是存储数据元素的数据域,一个是存储下一个结点地质的指针域
stl中的链表是一个双向循环链表
stl中链表结构
链表存储方式不是连续的空间,因此链表中迭代器只支持前移和后移,属于双向迭代器
list优点:
1 动态分配内存,不会造成浪费
2 插入和删除都很方便,修改指针即可
list缺点:
1 空间和时间开销比较大,存放指针域和逐次遍历
list构造函数
list<int>q;
q.push_back(1);
q.push_back(2);
q.push_back(3);
q.push_back(4);
printl(q);
list<int>l1(q.begin(), q.end());
printl(l1);
list赋值和交换
list<int>q;
q.push_back(1);
q.push_back(2);
q.push_back(3);
q.push_back(4);
printl(q);//1 2 3 4
list<int>l1;
l1.push_back(5);
l1.push_back(6);
l1.push_back(7);
l1.push_back(8);
printl(l1);// 5 6 7 8
q.swap(l1);
printl(l1);//1 2 3 4
list大小操作
list<int>q;
q.push_back(1);
q.push_back(2);
q.push_back(3);
q.push_back(4);
cout << q.size() << endl;//4
q.resize(10);//重新指定大小
cout << q.size() << endl;//10
list插入和删除
list删除和插入都可以在两端,也可以在指定位置插入删除,但传入的位置参数都得是迭代器,不能是index。如果要删除指定元素,也可以用remove操作。
list<int>q;
q.push_back(1);
q.push_back(2);
q.push_back(3);
q.push_back(4);//尾插
q.push_front(5);//头插
q.pop_back();//尾删
q.pop_front();//头删
pl(q);//1 2 3
list<int>::iterator it = q.begin();
q.insert(++it, 100);//1 100 2 3
pl(q);
//删除
it = q.begin();
q.erase(it);//删除操作传入的是迭代器
pl(q);//100,2,3
q.push_back(10000);
q.remove(10000);//删除指定元素值
pl(q);
q.clear();//清空list全部数据
list反转和排序
不可以随机访问的容器,不能用标准算法,只能用容器提供的自带的算法。不可用全局函数
list<int>q;
q.push_back(1);
q.push_back(2);
q.push_back(3);
q.push_back(4);//尾插
q.push_front(5);//头插
pl(q);//1 2 3
q.reverse();
pl(q);//1 2 3
//不支持随机访问的迭代器,不可以用标准算法
q.sort();//排序方式这样写
pl(q);
q.sort(mycompare);//降序排列
pl(q);
排序案例
排序自定义的数据类型。
class person {//定义person的类别
public:
person(string name, int age, int height) {
this->m_name = name;
this->m_age = age;
this->m_height = height;
}
string m_name;
int m_age;
int m_height;
};
//指定排序规则
bool compareperson(person&p1, person&p2) {//定义排序函数
//年龄按照升序
if (p1.m_age == p2.m_age) {
return p1.m_height > p2.m_height;
}
else {
return p1.m_age < p2.m_age;
}
}
int main()
{
list<person>li;
person p1("kobe", 24, 8);
person p2("james", 23, 6);
person p3("paul", 3, 9);
person p4("durant", 35, 5);
person p5("yaoming", 11, 12);
li.push_back(p1);
li.push_back(p2);
li.push_back(p3);
li.push_back(p4);
li.push_back(p5);
for (list<person>::iterator it = li.begin(); it != li.end(); it++) {
cout << it->m_name << " " << it->m_age << " " << it->m_height << endl;
}
li.sort(compareperson);
cout << "自定义排序规则之后。。。。。。。。。。" << endl;
for (list<person>::iterator it = li.begin(); it != li.end(); it++) {
cout << it->m_name << " " << it->m_age << " " << it->m_height << endl;
}
}
set/multiset容器
set容器:
所有元素插入时候都会被排好序
本质:
属于关联式容器,底层结构是二叉树
区别:
set不允许容器中有重复元素
multiset允许容器中有重复元素
void prints(set<int>&s) {
for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
int main()
{
set<int>s1;
s1.insert(1);
s1.insert(3);
s1.insert(3);
s1.insert(4);
s1.insert(4);
prints(s1);
}
set大小和交换
set<int>s1;
s1.insert(1);
s1.insert(3);
s1.insert(2);
s1.insert(4);
s1.insert(4);
cout << s1.size() << endl;//4
set<int>s2;
s2.insert(7);
s2.insert(86);
s2.insert(45);
s2.insert(34);
s2.insert(98);
s1.swap(s2);
prints(s2);
set插入和删除
set<int>s1;
s1.insert(1);
s1.insert(3);
s1.insert(2);
s1.insert(4);
s1.insert(4);
cout << s1.size() << endl;//4
auto it = s1.begin();
s1.erase(it);//传入迭代器进行删除
prints(s1);
s1.erase(4);//可以直接删除某一个数
prints(s1);
s1.clear();//清空全部数据
set查找和统计
对set容器内数据进行查找和统计
find(key)//找到了返回该数据的迭代器,找不到返回末尾数据的迭代器
count(key)//统计key的个数
set<int>s1;
s1.insert(1);
s1.insert(3);
s1.insert(2);
s1.insert(4);
s1.insert(4);
cout << s1.size() << endl;//4
prints(s1);
set<int>::iterator it=s1.find(1);
if (it != s1.end()) {
cout << "find it " <<*it<< endl;
}
else cout << "not exist" << endl;
cout << s1.count(2) << endl;
se和multiset的区别
1 set不允许插入重复数据,multiset允许
2 set插入数据同时会返回插入结果,表示是否插入成功
3 multiset不会检查数据,因此可以重复插入
set<int>s1;
s1.insert(10);
pair<set<int>::iterator,bool> ret = s1.insert(10);//检查数据是否插入成功
if (ret.second == true) {
cout << "插入成功" << endl;
}
else {
cout << "failed" << endl;
}
multiset<int>s2;//multiset运行重复插入数据
s2.insert(10);
s2.insert(10);
for (multiset<int>::iterator it = s2.begin(); it != s2.end(); it++) {
cout << *it << endl;
}
pair对组的创建
成对出现的数据,利用对组可以返回两个数据
set<int>s1;
s1.insert(10);
pair<string, int>p("kobe", 24);
cout << p.first << " " << p.second << endl;
内置类型指定排序规则
在还没插入数据之前就要指定插入规则
需要重载运算符,需要自己写一个仿函数。
class mycompare {//需要重载运算符
public:
bool operator()(int a,int b){
return a > b;
}
};
int main()
{
set<int,mycompare>s1;
s1.insert(10);
s1.insert(50);
s1.insert(20);
s1.insert(5);
for (set<int, mycompare>::iterator it = s1.begin(); it != s1.end(); it++) {
cout << *it << " ";
}
cout << endl;
pair<string, int>p("kobe", 24);
自定义类型指定排序规则
class person {//定义person的类别
public:
person(string name, int age, int height) {
this->m_name = name;
this->m_age = age;
this->m_height = height;
}
string m_name;
int m_age;
int m_height;
};
//指定排序规则
class comparep {
public :
bool operator()(const person&p1, const person&p2) {
if (p1.m_age == p2.m_age) {
return p1.m_height > p2.m_height;
}
else {
return p1.m_age > p2.m_age;
}
}
};
int main()
{
set<person, comparep >s;//此时的set容器需要提前指定排序规则
person p1("kobe", 24, 8);
person p2("james", 6, 23);
person p3("jordan", 23, 3);
person p4("durant", 35, 11);
s.insert(p1);
s.insert(p2);
s.insert(p3);
s.insert(p4);
//迭代器也需要指定排序规则
for (set<person, comparep>::iterator it = s.begin(); it != s.end(); it++) {
cout <<it->m_name<< it->m_name << " " << it->m_age << endl;
}
map/multimap容器
map中的元素都是pair
pair中第一个元素是key(键值),第二个元素是value(实值)
所有元素都会根据元素的键值进行排序
map/multimap属于关联式容器,底层是二叉树结构
优点:
可以根据key快速的找到value
map不允许有重复的key值元素
multimap允许有重复的key值
构造函数
void printm(map<int, int>&m) {
for (map<int, int>::iterator it = m.begin(); it != m.end(); it++) {
cout << it->first << " " << (*it).second << endl;
}
}
int main()
{
map<int, int>m;
m.insert(pair<int, int>(1, 10));//匿名对组,
m.insert(pair<int, int>(3, 30));
m.insert(pair<int, int>(2, 60));
printm(m);//根据键值自动排序
map<int, int>m1;
m1 = m;
map<int, int>m2(m);
printm(m);//根据键值自动排序
map容器大小和交换
cout << m.size() << endl;
map插入和删除
插入方式有四种
但不太推荐第4种方式,要是插入错了,会默认添加value为0的,可以利用第四种方式去访问数据。
map<int, int>m;
m.insert(pair<int, int>(1, 10));//匿名对组,
m.insert(pair<int, int>(3, 30));
m.insert(pair<int, int>(2, 60));//第一种插入方法
m.insert(make_pair(4, 50));//第二种插入方法
m.insert(map<int, int>::value_type(8, 12));//第三种插入方法
m[23] = 34;//第四种插入方法
删除操作
map<int, int>m;
m.insert(pair<int, int>(1, 10));//匿名对组,
m.insert(pair<int, int>(3, 30));
m.insert(pair<int, int>(2, 60));//第一种插入方法
m.insert(make_pair(4, 50));//第二种插入方法
m.insert(map<int, int>::value_type(8, 12));//第三种插入方法
m[23] = 34;//第四种插入方法
printm(m);
m.erase(m.begin());
printm(m);
m.erase(3);//按照键值删除
m.erase(m.begin(), m.end());//按照区间进行删除
m.clear();//清空全部数据
map查找和统计
find返回的是一个迭代器,如果没找到就返回末尾元素位置的迭代器。
map<int, int>m;
m.insert(pair<int, int>(1, 10));//匿名对组,
m.insert(pair<int, int>(3, 30));
m.insert(pair<int, int>(2, 60));//第一种插入方法
m.insert(make_pair(4, 50));//第二种插入方法
m.insert(map<int, int>::value_type(8, 12));//第三种插入方法
m[23] = 34;//第四种插入方法
printm(m);
map<int,int>::iterator pos = m.find(5);//按照key值进行查找,返回的是迭代器
if (pos != m.end()) {
cout << "找到了" << pos->first << " " << pos->second << endl;
}
else {
cout << "没找到" << endl;
}
统计操作
统计的是key值
如果是map结果只能是0/1
如果是multimap则结果可能是其他值
map排序
利用仿函数去重载排序规则
默认按照key值进行升序排序
map<int,int,sortmap>m;
m.insert(make_pair(1, 10));//匿名对组,
m.insert(make_pair(3, 30));
m.insert(make_pair(2, 60));//
m.insert(make_pair(4, 50));//
for (map<int, int, sortmap>::iterator it = m.begin(); it != m.end(); it++) {
cout << it->first << " " << it->second << endl;
}
员工分组
class worker {//定义员工的类
public:
/*worker(string name, int salary) {
this->m_name = name;
this->m_salary = salary;
}*/
string m_name;
int m_salary;
};
void creatework(vector<worker>&v) {//实例化员工
string nameseed = "ABCDEFGHIJ";
for(int i = 0; i < 10; i++) {
worker w;
w.m_name = "员工";
w.m_name += nameseed[i];
w.m_salary = rand() % 10000 + 10000;
v.push_back(w);
}
}
void setgroup(vector<worker>&v, multimap<int, worker>&mv) {//给员工分组
for (vector<worker>::iterator it = v.begin(); it != v.end(); it++) {
//产生随机部门的编号
int depid = rand() % 3;//0 1 2
//利用multimap将员工信息插入进去
//key代表部门编号
mv.insert(make_pair(depid,*it));
}
}
void showwork(multimap<int, worker>&mv) {//显示处员工分组信息
cout << "策划部门" << endl;
multimap<int, worker>::iterator pos = mv.find(0);
int count = mv.count(0);
int index = 0;
for (; pos != mv.end()&&index<count; pos++,index++) {
cout << pos->second.m_name << " " << pos->second.m_salary << endl;
}
}
int main()
{ //创建员工
vector<worker>v;
creatework(v);
/*for (vector<worker>::iterator it = v.begin(); it != v.end(); it++) {
cout << it->m_name << " " << it->m_salary << endl;
}*/
//员工分组
multimap<int, worker>mv;
setgroup(v,mv);
/*for (multimap<int, worker>::iterator it = mv.begin(); it != mv.end(); it++) {
cout << it->first<< endl;
}*/
//分组显示员工信息
showwork(mv);
system("pause");