文章目录
- 一、stack容器
- 二、queue容器
- 三、list容器
- 1、构造函数
- 2、赋值和交换
- 3、大小及判空
- 4、插入和删除
- 5、数据存取
- 6、反转和排序
- 7、排序案例
- 四、set/multiset容器
- 1、构造和赋值
- 2、大小和交换
- 3、插入和删除
- 4、查找和统计
- 5、set和multiset的区别
- 6、pair对组的创建
- 7、排序及规则改变
- 五、map/multimap容器
- 1、构造和赋值
- 2、大小和交换
- 3、插入和删除
- 4、查找和统计
- 5、排序及规则改变
- 六、员工分组案例
一、stack容器
stack是一种后进先出的数据结构,栈中只有栈顶元素才可以被外界使用,所以栈不允许有遍历行为。
栈可以进行判空操作,也可以统计栈中的元素数量。
stack容器常用的接口有以下几个。
//构造函数
stack<T> stk; //默认构造函数
stack(const stack &stk); //拷贝构造函数
//赋值操作
stack& operator=(const stack &stk); //=赋值操作
//数据存取
push(elem); //向栈顶添加元素
pop(); //删除栈顶元素
top(); //返回栈顶元素
//大小操作
empty(); //判空
size(); //返回栈的大小
关于栈容器的简单操作示例如下。
#include <iostream>
#include <stack>
using namespace std;void fun()
{stack<int> s;s.push(1);s.push(2);s.push(3);s.push(4);cout<<"栈的大小为:"<<s.size()<<endl;while(!s.empty()){cout<<"栈顶元素:"<<s.top()<<endl;s.pop(); //出栈}cout<<"栈的大小为:"<<s.size()<<endl;
}int main()
{fun();system("pause");return 0;
}
上面程序的运行结果如下图所示。
二、queue容器
queue是一种先进先出的数据结构,queue容器允许从一端新增元素,从另一端移除元素。队列中只有队头和队尾才可以被外界使用,因此队列不允许有遍历行为。
queue容器常用的接口有以下几个。
//构造函数
queue<T> que; //默认构造函数
queue(const queue &que); //拷贝构造函数
//赋值操作
queue& operator=(const queue &que); //=赋值操作
//数据存取
push(elem); //往队尾添加元素
pop(); //删除队头元素
back(); //返回最后一个元素
front(); //返回第一个元素
//大小操作
empty(); //判空
size(); //返回队列的大小
关于队列容器的简单操作示例如下。
#include <iostream>
#include <queue>
using namespace std;void fun()
{queue<int> q;q.push(1);q.push(2);q.push(3);q.push(4);cout<<"队列的大小为:"<<q.size()<<endl;while(!q.empty()){cout<<"队头元素:"<<q.front()<<endl;cout<<"队尾元素:"<<q.back()<<endl;q.pop();}cout<<"队列的大小为:"<<q.size()<<endl;
}int main()
{fun();system("pause");return 0;
}
三、list容器
链表由一系列结点组成,结点由存储数据元素的数据域和存储下一个结点地址的指针域构成。
链表将数据进行链式存储,是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的。STL中的链表是一个双向循环链表。
链表的优点是其采用动态存储分配,不会造成内存的浪费和溢出,而且链表执行插入和删除操作十分方便,只需要修改指针,不需要移动大量元素。缺点是遍历的速度没有数组快,因为数据不是连续存放的,此外,链表占用的空间也比数组大,相比于数组只存放数据,链表还需要存放地址。
由于链表的存储方式并不是连续的内存空间,因此链表list中的迭代器只支持前移和后移操作,也就是只能做++和–运算,不能一次跳几个,其属于双向迭代器。
list容器有一个重要的性质,插入和删除操作都不会造成原有list迭代器的失效。这在vector中是不成立的,如果将vector的容量进行扩充,那么其迭代器就会失效。
1、构造函数
list容器常用的接口有以下几个。
list<T> lst; //默认构造函数
list(begin,end); //将区间元素进行拷贝
list(n,elem); //将n个元素进行拷贝
list(const list &lst); //拷贝构造函数
关于list容器构造函数的简单代码示例如下。
#include <iostream>
#include <list>
using namespace std;void printList(const list<int> &L)
{for(list<int>::const_iterator i=L.begin();i!=L.end();i++){cout<<*i<<" ";}cout<<endl;
}void fun()
{list<int> L1; //默认构造L1.push_back(1);L1.push_back(2);L1.push_front(3);L1.push_front(4);printList(L1);list<int> L2(L1.begin(),L1.end()); //复制区间构造printList(L2);list<int> L3(5,6); //指定长度和元素构造printList(L3);list<int> L4(L3); //拷贝构造printList(L4);
}int main()
{fun();system("pause");return 0;
}
2、赋值和交换
与前面介绍过的容器一样,list容器赋值包括=赋值和assign赋值,交换仍然使用swap()函数。
关于list容器赋值和交换的简单示例如下。
#include <iostream>
#include <list>
using namespace std;void printList(const list<int> &L)
{for(list<int>::const_iterator i=L.begin();i!=L.end();i++){cout<<*i<<" ";}cout<<endl;
}void fun()
{list<int> L1;L1.push_back(1);L1.push_back(2);L1.push_front(3);L1.push_front(4);cout<<"L1 : ";printList(L1);list<int> L2;L2 = L1; // = 赋值cout<<"L2 : ";printList(L2);list<int> L3;L3.assign(L2.begin(),L2.end()); //assign区间赋值cout<<"L3 : ";printList(L3);list<int> L4;L4.assign(6,6); //指定数字赋值cout<<"L4 : ";printList(L4);L1.swap(L4); //使用swap()交换两个容器cout<<"交换L1和L4后:"<<endl;cout<<"L1 : ";printList(L1);cout<<"L4 : ";printList(L4);
}int main()
{fun();system("pause");return 0;
}
上面程序运行后的结果如下图所示。
3、大小及判空
list容器的大小及判空操作与前面介绍的容器一样,简单的代码示例如下。
void fun()
{list<int> L1;L1.push_back(1);L1.push_back(2);L1.push_front(3);L1.push_front(4);printList(L1);if(!L1.empty()){cout<<"容器不为空!"<<endl;cout<<"容器中的元素个数:"<<L1.size()<<endl;}L1.resize(7);printList(L1);L1.resize(10,6);printList(L1);
}
4、插入和删除
插入和删除的主要函数接口有以下几个。
push_front(elem); //在容器头部插入一个数据
push_back(elem); //在容器尾部插入一个数据
pop_front(); //从容器头部删除一个数据
pop_back(); //从容器尾部删除一个数据insert(pos,elem); //在指定位置插入指定元素,要用迭代器,不能用数字索引
insert(pos,n,elem); //在指定位置插入n个指定元素
insert(pos,start_pos,end_pos); //从指定位置开始插入区间数据
clear(); //清空数据
erase(pos); //删除指定位置的数据
erase(start_pos,end_pos); //删除指定区间的数据
remove(elem); //删除容器中所有和elem值匹配的元素
关于插入和删除的操作,list容器中多了一个remove操作,简单的示例如下。
#include <iostream>
#include <list>
using namespace std;void printList(const list<int> &L)
{for(list<int>::const_iterator i=L.begin();i!=L.end();i++){cout<<*i<<" ";}cout<<endl;
}void fun()
{list<int> L1;L1.push_back(1);L1.push_front(2);printList(L1);L1.insert(L1.begin(),3);L1.insert(++L1.begin(),4,6);printList(L1);L1.erase(--L1.end());printList(L1);L1.remove(6); //移除容器中所有的6printList(L1);
}int main()
{fun();system("pause");return 0;
}
上面程序运行后的结果如下图所示。
5、数据存取
list容器不同于vector和deque容器,其数据存取不支持中括号[]和at()方式,只能使用front()和back()返回第一个和最后一个元素。
关于list容器数据存取操作的简单代码示例如下。
void fun()
{list<int> L1;L1.push_back(1);L1.push_front(2);L1.push_back(3);L1.push_front(4);printList(L1);cout<<"第一个元素为: "<<L1.front()<<endl;cout<<"最后一个元素为: "<<L1.back()<<endl;
}
验证迭代器是不是支持随机访问且是双向的。
list<int>::iterator i=L.begin();
i++;
i--; //i++和i--都不报错就是支持双向访问
i = i+1; //报错就说明不支持随机访问
6、反转和排序
list容器的反转和排序分别使用下面的函数。
reverse(); //反转链表
sort(); //将链表进行排序,成员函数,非全局函数
由于迭代器在list容器中不可以随机访问,因此不能使用标准的算法,但是内部会提供一些函数接口,使用.访问,而不是全局函数。
list容器的反转和排序简单示例如下。
#include <iostream>
#include <algorithm>
#include <list>
using namespace std;void printList(const list<int> &L)
{for(list<int>::const_iterator i=L.begin();i!=L.end();i++){cout<<*i<<" ";}cout<<endl;
}bool myrule(int a,int b) //排序规则
{return a > b;
}void fun()
{list<int> L1;L1.push_back(2);L1.push_back(1);L1.push_back(4);L1.push_back(3);cout<<"原序列 :";printList(L1);L1.reverse();cout<<"原序列反转后 :";printList(L1);L1.sort(); //默认升序排列cout<<"原序列升序排列后 :";printList(L1);L1.sort(myrule); //降序排列cout<<"原序列降序排列后 :";printList(L1);
}int main()
{fun();system("pause");return 0;
}
上面程序运行后的结果如下图所示。
7、排序案例
将自定义数据类型Person进行排序,排序按照年龄升序排列,如果年龄相同则按照身高降序排列。Person中的属性包括姓名、年龄、身高。
该案例的代码实现如下。
#include <iostream>
#include <algorithm>
#include <list>
#include <string>
using namespace std;class Person
{
public:Person(string name,int age,int height){this->name = name;this->age = age;this->height = height;}string name;int age;int height;
};void printList(const list<Person> &L)
{for(list<Person>::const_iterator i=L.begin();i!=L.end();i++){cout<<"姓名: "<<(*i).name<<" 年龄: "<<(*i).age<<" 身高: "<<(*i).height<<endl;}
}bool sortPerson(Person &p1,Person &p2) //排序规则
{if(p1.age == p2.age){return p1.height > p2.height; //在年龄相同时按照身高降序}return p1.age<p2.age; //按照年龄升序排列
}void fun()
{Person p1("A",20,185);Person p2("B",20,175);Person p3("C",20,176);Person p4("D",18,191);Person p5("E",23,186);list<Person> L;L.push_back(p1);L.push_back(p2);L.push_back(p3);L.push_back(p4);L.push_back(p5);cout<<"------------排序前------------"<<endl;printList(L);L.sort(sortPerson);cout<<"------------排序后------------"<<endl;printList(L);
}int main()
{fun();system("pause");return 0;
}
上面程序运行后的结果如下图所示。
本案例中涉及到对自定义数据类型的排序,需要自己指定相应的排序规则,然后传入sort()函数中即可。
四、set/multiset容器
set/multiset容器的特点是所有元素在插入时自动被排序,容器的本质是关联式容器,底层结构用二叉树实现。
set容器和multiset容器的区别在于,set容器不允许容器中有重复的元素,而multiset容器中允许出现重复的元素。
set/multiset容器插入数据时没有push()或push_back(),只能用insert()函数来插入数值。
1、构造和赋值
构造包括默认构造和拷贝构造,赋值通过=实现。
set容器关于构造和赋值的操作示例如下。
#include <iostream>
#include <set>
using namespace std;void printSet(const set<int> &s)
{for(set<int>::const_iterator i=s.begin();i!=s.end();i++){cout<<*i<<" ";}cout<<endl;
}void fun()
{set<int> s1; //默认构造s1.insert(2); //插入数据用insert()s1.insert(1);s1.insert(2);s1.insert(4);s1.insert(2);s1.insert(3);cout<<"s1 : ";printSet(s1);set<int> s2(s1); //拷贝构造cout<<"s2 : ";printSet(s2);set<int> s3;s3 = s1; //赋值操作cout<<"s3 : ";printSet(s3);
}int main()
{fun();system("pause");return 0;
}
上面程序运行后的结果如下图所示。
可以看到,在set容器中插入重复数据虽然不会报错,但也不会打印出来,而且插入无序的元素在打印的时候被排好序了。
2、大小和交换
set容器不支持重新定义容器大小,即没有resize()函数。
关于set容器大小、判空和交换的简单应用如下。
#include <iostream>
#include <set>
using namespace std;void printSet(const set<int> &s)
{for(set<int>::const_iterator i=s.begin();i!=s.end();i++){cout<<*i<<" ";}cout<<endl;
}void fun()
{set<int> s1;s1.insert(2);s1.insert(1);s1.insert(4);s1.insert(3);cout<<"s1 : ";printSet(s1);if(!s1.empty()){cout<<"容器非空,大小为: "<<s1.size()<<endl;}set<int> s2;s2.insert(20);s2.insert(10);s2.insert(40);s2.insert(30);cout<<"s2 : ";printSet(s2);cout<<"交换s1和s2容器后: "<<endl;s1.swap(s2);cout<<"s1 : ";printSet(s1);cout<<"s2 : ";printSet(s2);
}int main()
{fun();system("pause");return 0;
}
上面程序运行后的结果如下图所示。
3、插入和删除
set容器插入使用insert()函数,删除使用erase()函数,清空容器使用clear()函数。在使用erase()函数时,既可以传入迭代器的位置,也可以传入要删除的元素,当然也可以传入一个区间进行删除,传入迭代器的首尾位置,其作用和clear()函数一样。
关于set容器插入和删除的简单操作示例如下。
void fun()
{set<int> s1;s1.insert(2);s1.insert(1);s1.insert(4);s1.insert(3);printSet(s1);s1.erase(s1.begin()); //指定迭代器的位置进行删除printSet(s1);s1.erase(3); //指定容器中的元素进行删除printSet(s1);s1.clear(); //清空容器,等价于 s1.erase(s1.begin(),s1.end());printSet(s1);
}
4、查找和统计
set容器中进行查找使用的函数是find(elem),查找元素elem是否存在,其返回值是一个迭代器,如果该元素存在,就返回该元素的迭代器,如果不存在,就返回end()。
set容器中统计元素的个数使用的函数是count(elem),但是其结果只能是0或1,对于multiset容器而言,count(elem)的结果可能大于1。
find(elem); //返回的是迭代器的位置
count(elem); //返回元素个数
关于set容器查找和统计的代码示例如下。
#include <iostream>
#include <set>
using namespace std;void printSet(const set<int> &s)
{for(set<int>::const_iterator i=s.begin();i!=s.end();i++){cout<<*i<<" ";}cout<<endl;
}void fun()
{set<int> s1;s1.insert(2);s1.insert(1);s1.insert(2);s1.insert(2);s1.insert(4);s1.insert(3);printSet(s1);set<int>::iterator pos = s1.find(2);if(pos!=s1.end()){cout<<"元素"<<*pos<<"存在!"<<endl;cout<<"元素"<<*pos<<"的个数: "<<s1.count(*pos)<<endl;}else{cout<<"元素不存在!"<<endl;}
}int main()
{fun();system("pause");return 0;
}
上面程序运行后的结果如下图所示。
5、set和multiset的区别
set不可以插入重复数据,其在插入的同时会返回插入结果,反馈是否插入成功,multiset不会检测数据,所以允许插入重复的数据。
set使用插入insert()时,转到其定义如下,再转到Pairib的定义。
template<class _Valty>_Pairib insert(_Valty&& _Val){ // try to insert node with value _Val, favoring right sidereturn (_Linsert(this->_Buynode(_STD forward<_Valty>(_Val)),false));}typedef pair<iterator, bool> _Pairib; //pair是对组,返回的不仅有迭代器,还有bool类型,即插入成功与否
multiset使用插入insert()时,转到其定义如下。
template<class _Valty>iterator insert(_Valty&& _Val){ // insert a {key, mapped} valuereturn (_Mybase::insert(_STD forward<_Valty>(_Val)).first);}
可以看到,multiset在插入时返回值是一个迭代器类型,不像set容器返回的是pair对组,因此在插入时不做判断,即使元素重复也能插入成功。
关于set和multiset容器的区别,简单的代码示例如下。
#include <iostream>
#include <set>
using namespace std;void printSet(const multiset<int> &ms)
{for(multiset<int>::const_iterator i=ms.begin();i!=ms.end();i++){cout<<*i<<" ";}cout<<endl;
}void fun1()
{set<int> s;pair<set<int>::iterator,bool> ret = s.insert(2);if(ret.second){cout<<"元素第一次插入成功!"<<endl;}else{cout<<"元素第一次插入失败!"<<endl;}ret = s.insert(2);if(ret.second){cout<<"元素第二次插入成功!"<<endl;}else{cout<<"元素第二次插入失败!"<<endl;}
}void fun2() // multiset容器测试
{multiset<int> ms;ms.insert(2);ms.insert(2);ms.insert(2);printSet(ms);
}int main()
{fun1();fun2();system("pause");return 0;
}
上面程序运行后的结果如下图所示。
6、pair对组的创建
对组是指成对出现的数据,利用对组可以返回两个数据。
对组的两种创建方式如下。
pair<type,type> p(value1,value2);
pair<type,type> p = make_pair(value1,value2);
关于对组的简单应用代码如下。
#include <iostream>
#include <string>
#include <set>
using namespace std;void fun()
{pair<string,int> p1("Tom",10); //方式一cout<<"name: "<<p1.first<<" age: "<<p1.second<<endl;pair<string,int> p2 = make_pair("Jack",20); //方式二cout<<"name: "<<p2.first<<" age: "<<p2.second<<endl;
}int main()
{fun();system("pause");return 0;
}
上面程序运行后的结果如下图所示。
7、排序及规则改变
set容器默认排序规则为从小到大,使用仿函数就可以改变排序规则。
使用仿函数改变内置数据类型排序规则的代码示例如下。
#include <iostream>
#include <string>
#include <set>
using namespace std;class Compare
{
public:bool operator()(int a,int b) //重载(){return a > b;}
};void printSet(set<int,Compare> &s)
{for(set<int,Compare>::iterator i=s.begin();i!=s.end();i++){cout<<*i<<" ";}cout<<endl;
}void fun()
{set<int,Compare> s1; //尖括号里携带的是类型,不能是函数s1.insert(2);s1.insert(3);s1.insert(1);s1.insert(4);printSet(s1);
}int main()
{fun();system("pause");return 0;
}
上面程序运行后输出的元素就是按照降序排列的。
使用仿函数改变自定义数据类型排序规则的代码示例如下。
#include <iostream>
#include <string>
#include <set>
using namespace std;class Person
{
public:Person(string name,int age){this->name = name;this->age = age;}string name;int age;
};class Compare
{
public:bool operator()(const Person &p1,const Person &p2) //重载(),规定排序类型{return p1.age > p2.age; //按年龄降序排列}
};void printSet(set<Person,Compare> &s)
{for(set<Person,Compare>::iterator i=s.begin();i!=s.end();i++){cout<<"姓名: "<<i->name<<" 年龄: "<<i->age<<endl;}
}void fun()
{set<Person,Compare> s1;Person p1("A",10);Person p2("B",20);Person p3("C",30);Person p4("D",40);s1.insert(p1);s1.insert(p2);s1.insert(p3);s1.insert(p4);printSet(s1);
}int main()
{fun();system("pause");return 0;
}
上面程序运行后的结果如下图所示。
五、map/multimap容器
map容器中所有的元素都是对组pair型,pair中的第一个元素为key,即键值,第二个元素为value,即实值。map容器中的所有元素都会根据元素的键值自动排序。
map/multimap属于关联式容器,底层的结构是用二叉树实现的,其最大的优点是可以根据键值快速的找到value值。
map容器和multimap容器的区别在于,map容器不允许容器中有重复的键值key,而multimap容器中则允许有重复的键值。
1、构造和赋值
构造包括默认构造和拷贝构造两种,赋值通过=实现。插入操作仍然是使用insert()函数,不过在函数中需要声明类型是pair,然后再传值。
关于map容器构造和赋值的操作示例如下。
#include <iostream>
#include <map>
using namespace std;void printSet(map<int,int> &m)
{for(map<int,int>::iterator i=m.begin();i!=m.end();i++){cout<<"key: "<<(*i).first<<" value: "<<(*i).second<<endl;}
}void fun()
{map<int,int> m; //默认构造m.insert(pair<int,int>(1,10));m.insert(pair<int,int>(4,40));m.insert(pair<int,int>(3,30));m.insert(pair<int,int>(2,20));cout<<"m : "<<endl;printSet(m); map<int,int> m1(m); //拷贝构造cout<<"m1 : "<<endl;printSet(m1); map<int,int> m2;m2 = m; //赋值操作cout<<"m2 : "<<endl;printSet(m2);
}int main()
{fun();system("pause");return 0;
}
上面程序运行后的结果如下图所示。
2、大小和交换
关于map容器大小、判空和交换的简单应用如下。
#include <iostream>
#include <map>
using namespace std;void printSet(map<int,int> &m)
{for(map<int,int>::iterator i=m.begin();i!=m.end();i++){cout<<"key: "<<(*i).first<<" value: "<<(*i).second<<endl;}
}void fun()
{map<int,int> m; //默认构造m.insert(pair<int,int>(1,10));m.insert(pair<int,int>(2,20));if(!m.empty()){cout<<"容器非空,大小为: "<<m.size()<<endl;}else{cout<<"容器为空!"<<endl;}cout<<"------交换前------"<<endl;cout<<"m : "<<endl;printSet(m); map<int,int> m1;m1.insert(pair<int,int>(3,30));m1.insert(pair<int,int>(4,40));cout<<"m1 : "<<endl;printSet(m1); cout<<"------交换后------"<<endl;m.swap(m1);cout<<"m : "<<endl;printSet(m); cout<<"m1 : "<<endl;printSet(m1);
}int main()
{fun();system("pause");return 0;
}
上面程序运行后的结果如下图所示。
3、插入和删除
map容器插入使用insert()函数,删除使用erase()函数,清空容器使用clear()函数。在使用erase()函数时,既可以传入迭代器的位置,也可以传入要删除的元素,当然也可以传入一个区间进行删除,传入迭代器的首尾位置,其作用和clear()函数一样。插入的方式总共有四种。
关于map容器插入和删除的简单操作示例如下。
#include <iostream>
#include <map>
using namespace std;void printSet(map<int,int> &m)
{for(map<int,int>::iterator i=m.begin();i!=m.end();i++){cout<<"key: "<<(*i).first<<" value: "<<(*i).second<<endl;}cout<<endl;
}void fun()
{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为0的出来cout<<m[5]<<endl;printSet(m);m.erase(5); //按照键值key删除m.erase(m.begin()); //按照迭代器位置删除printSet(m);m.clear(); //清空,等价于m.erase(m.begin(),m.end());printSet(m);}int main()
{fun();system("pause");return 0;
}
上面程序运行后的结果如下图所示。
4、查找和统计
map容器中进行查找使用的函数是find(elem),查找元素elem是否存在,其返回值是一个迭代器,如果该元素存在,就返回该元素的迭代器,如果不存在,就返回end()。
map容器中统计元素的个数使用的函数是count(elem),但是其结果只能是0或1,对于multimap容器而言,count(elem)的结果可能大于1。
find(elem); //返回的是迭代器的位置
count(elem); //返回元素个数
关于map容器查找和统计的代码示例如下。
#include <iostream>
#include <map>
using namespace std;void fun()
{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)); map<int,int>::iterator pos = m.find(2);if(pos!=m.end()){cout<<"元素存在! key = "<<(*pos).first<<" value = "<<(*pos).second<<endl;cout<<"键值"<<(*pos).first<<"的个数: "<<m.count((*pos).first)<<endl;}else{cout<<"元素不存在!"<<endl;}
}int main()
{fun();system("pause");return 0;
}
上面程序运行后的结果如下图所示。
5、排序及规则改变
map容器默认排序规则仍然是从小到大,通过自己写仿函数就可以改变排序规则。
使用仿函数改变内置数据排序规则的代码示例如下。
#include <iostream>
#include <map>
using namespace std;class Compare
{
public:bool operator()(int a,int b){return a > b;}
};void fun()
{map<int,int,Compare> m;m.insert(pair<int,int>(1,10));m.insert(make_pair(2,20));m.insert(map<int,int>::value_type(3,30)); for(map<int,int,Compare>::iterator i=m.begin();i!=m.end();i++){cout<<"key = "<<i->first<<" value = "<<i->second<<endl;}
}int main()
{fun();system("pause");return 0;
}
上面程序运行后的结果如下图所示。
这里需要注意的是,map容器中是对key进行排序的,如果要按照自定义数据的属性进行排序,需要把自定义数据类型放在map容器的第一个位置上。
使用仿函数改变自定义数据排序规则的代码示例如下。
#include <iostream>
#include <string>
#include <map>
using namespace std;class Person
{
public:Person(string name,int age){this->name = name;this->age = age;}string name;int age;
};class Compare
{
public:bool operator()(Person p1,Person p2){return p1.age > p2.age;}
};void fun()
{map<Person,int,Compare> m;Person p1("Tom",10);Person p2("Jack",30);Person p3("Hole",20);m.insert(pair<Person,int>(p1,1));m.insert(pair<Person,int>(p2,2));m.insert(pair<Person,int>(p3,3));for(map<Person,int,Compare>::iterator i=m.begin();i!=m.end();i++){cout<<"key = "<<i->second<<" name = "<<i->first.name<<" age = "<<i->first.age<<endl;}
}int main()
{fun();system("pause");return 0;
}
上面程序运行后的结果如下图所示。
从输出结果可以看出,排序是按照自定义数据的年龄属性降序排列的。
六、员工分组案例
公司招聘了10个员工ABCDEFGHIJ,现在需要指派员工在那个部门工作,员工信息包括姓名和工资,部门分为策划、美术、研发。随机给10名员工分配部门和工资,通过multimap容器进行信息的插入,key表示部门编号,value表示员工,可以分部门显示员工信息。
实现步骤:创建10名员工,放到vector中;遍历vector容器,取出每个员工,进行随机分组;分组后,将员工部门编号作为key,具体员工作为value,放入到multimap容器中;分部门显示员工信息。
该案例的代码实现如下。
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <ctime>
using namespace std;class Staff
{
public:Staff(string name,int wage){this->name = name;this->wage = wage;}string name;int wage;
};void createStaff(vector<Staff> &v)
{string nameSeed = "ABCDEFGHIJ";for(int i=0;i<10;i++){string name = "员工";name += nameSeed[i];int wage = rand()%1000+3000; //3000-3999Staff s(name,wage);v.push_back(s);}
}void setGroup(vector<Staff> &v,multimap<int,Staff> &m)
{for(vector<Staff>::iterator i=v.begin();i!=v.end();i++){int dep_num = rand()%3+1; //1-3 1策划、2美术、3研发m.insert(make_pair(dep_num,*i)); //给员工分配部门}
}void showInfo(multimap<int,Staff> &m)
{cout<<"--------策划部门--------"<<endl;multimap<int,Staff>::iterator pos = m.find(1); //找到起始位置for(int i=0;i<m.count(1) && pos!=m.end();i++) //数量{cout<<"姓名: "<<pos->second.name<<" 工资:"<<pos->second.wage<<endl;++pos;}cout<<"--------美术部门--------"<<endl;pos = m.find(2);for(int i=0;i<m.count(2) && pos!=m.end();i++){cout<<"姓名: "<<pos->second.name<<" 工资:"<<pos->second.wage<<endl;++pos;}cout<<"--------研发部门--------"<<endl;pos = m.find(3);for(int i=0;i<m.count(3) && pos!=m.end();i++){cout<<"姓名: "<<pos->second.name<<" 工资:"<<pos->second.wage<<endl;++pos;}
}void printStaff(vector<Staff> &v)
{for(vector<Staff>::iterator i=v.begin();i!=v.end();i++){cout<<"name : "<<i->name<<" wage : "<<i->wage<<endl;}
}int main()
{srand((unsigned int)time(NULL)); //加入随机数种子,保证生成数的随机性vector<Staff> v; //创建vector容器createStaff(v); //创建员工信息printStaff(v);multimap<int,Staff> m; //创建multimap容器setGroup(v,m); //员工分组showInfo(m); //分组显示员工信息system("pause");return 0;
}
案例的运行结果如下图所示。
本文参考视频:
黑马程序员匠心之作|C++教程从0到1入门编程,学习编程不再难