目录
1 deque容器
1.1 deque容器基本概念---双端数组,可以对头端进行插入删除操作
1、deque与vector区别:
(1)vector对于头部的插入删除效率低,数据量越大,效率越低;
(2)deque相对而言,对头部的插入删除速度比vector快;
(3)vector访问元素的速度会比deque快,这和两者内部实现有关;
deque容器的迭代器也是支持随机访问的
1.1 deque构造函数-头文件<deque>
void MyPrint(const deque<int>& d)//传入const防止修改
{
for(deque<int>::const_iterator it=d.begin();it!=d.end();it++)
cout<<*it<<" ";
}
1.2 deque容器-赋值操作
1.3 deque容器-大小操作 ,没有容量概念
1.4 deque容器-插入和删除
deque<int>::iterator it=d1.begin();
it++;
d1.erase(it);
总结:插入和删除提供的位置是迭代器(指针)!!!
1.5 deque容器-数据存取
总结:除了用迭代器获取deque容器中的元素,[]和at也可以
1.6 deque容器-排序操作---包含头文件<algorithm>
总结:(1)排序,默认排序规则,从小到大,升序;
(2)对于支持随机访问的迭代器的容器,都可以利用sort算法直接对其进行排序
(3)vector容器也可以利用sort进行排序;
2 案例---评委打分
有5名选手ABCDE,10个评委分别对每一名选手打分,去除最高分,最低分,取平均分
实现步骤:
(1)创建5名选手,放到vector中;
(2)遍历vector容器,取出来每一个选手,执行for循环,把10个评分打分存到deque容器中;
(3)sort算法对deque容器中分数排序,去除最高分和最低分;
(4)deque容器遍历一遍,累加总分;
(5)获取平均分
//-------------练习1:List排序练习-------------------------
/*
将Person自定义数据类型进行排序,Person中属性有姓名、年龄、身高;
排序规则:按照年龄进行升序,如果年龄相同按照身高进行降序;
*/
//创建Person类
class 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 MySort(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;//年龄升序
}
void Show(list<Person>& L)
{
for(list<Person>::iterator it=L.begin();it!=L.end();it++)
{
cout<<"姓名:"<<(*it).m_Name<<" 年龄:"<<it->m_Age<<" 身高"<<(*it).m_Height<<endl;
}
}
void test()
{
//创建对象
Person P1("aaa",20,175);
Person P2("aaa",50,180);
Person P3("aaa",40,185);
Person P4("aaa",40,190);
Person P5("aaa",40,195);
Person P6("aaa",10,200);
//创建List容器
list<Person> L;
//填充数据-尾插法
L.push_back(P1);
L.push_back(P2);
L.push_back(P3);
L.push_back(P4);
L.push_back(P5);
L.push_back(P6);
Show(L);
//排序
L.sort(MySort);
cout<<"--------------------------------------"<<endl;
//显示
Show(L);
}
int main()
{
test();
return 0;
}
3 stack容器
3.1 stack概念---一种先进后出(First In Last Out,FILO)的数据结构,只有一个出口
栈中只有顶端的元素才可以被外界使用,
因此栈不允许有遍历行为,
栈中进入数据为---入栈(push);
栈中弹出数据为---出栈(pop);
3.2 stack常用接口
4 queue容器
4.1 queue概念---先进先出(First In First Out,FIFO)的数据结构,有两个出口
(1)队列容器允许从一端新增元素,从另一端移除元素;
(2)队列中只有队头和队尾才可以被外界使用,因此队列不允许有遍历行为;
(3)队列中进数据为---入队(push),队列中出数据为---出队(pop)
4.2 queue容器常用接口
5 list容器---链表
5.1 list基本概念
功能:将数据进行链式存储
链表(list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的。链表由一系列结点组成。
结点的组成:一个是存储数据元素的数据域,另一个是存储下一个结点的指针域
STL中的链表List是一个双向循环链表;
由于链表的存储方式并不是连续的内存空间,因此链表list中的迭代器只支持前移和后移,属于双向迭代器。
链表的优点:
(1)采用动态存储分配,不会造成内存浪费和溢出;
(2)链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素;
链表的缺点:
(1)链表灵活,但是空间(指针域+数据域)和时间(遍历)额外耗费较大;
List哟一个重要性质,插入操作和删除操作都不会造成原有List迭代器的失效,这在vector不成立;
总结:STL中List和Vector是最常被使用的容器,各有优缺点;
5.2 List 构造函数
5.3 List 赋值和交换
5.4 List 大小操作
5.5 List 插入和删除
注意:pos一般都是迭代器(指针)
5.6 List 数据存取
总结:list容器不可以通过[]或者at方式访问数据;
5.7 List 反转和排序---将容器中的元素反转,以及将容器中的数据进行排序
总结:所有不支持随机访问迭代器的容器,不可以用标准算法;
不支持随机访问迭代器的容器,内部会提供对应算法,自己的成员函数;
默认排序规则为从小到大,升序;
5.8 排序案例
//-------------练习1:List排序练习-------------------------
/*
将Person自定义数据类型进行排序,Person中属性有姓名、年龄、身高;
排序规则:按照年龄进行升序,如果年龄相同按照身高进行降序;
*/
//创建Person类
class 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 MySort(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;//年龄升序
}
//显示函数
void Show(list<Person>& L)
{
for(list<Person>::iterator it=L.begin();it!=L.end();it++)
{
cout<<"姓名:"<<(*it).m_Name<<" 年龄:"<<it->m_Age<<" 身高"<<(*it).m_Height<<endl;
}
}
void test()
{
//创建对象
Person P1("aaa",20,175);
Person P2("aaa",50,180);
Person P3("aaa",40,185);
Person P4("aaa",40,190);
Person P5("aaa",40,195);
Person P6("aaa",10,200);
//创建List容器
list<Person> L;
//填充数据-尾插法
L.push_back(P1);
L.push_back(P2);
L.push_back(P3);
L.push_back(P4);
L.push_back(P5);
L.push_back(P6);
Show(L);
//排序
L.sort(MySort);
cout<<"--------------------------------------"<<endl;
//显示
Show(L);
}
int main()
{
test();
return 0;
}
6 set/multiset容器
6.1 set概念---所有元素都会在插入时自动被排序
本质:set/multiset属于关联式容器,底层结构是用二叉树实现。
set和multiset区别:(1)set不允许容器中由重复的元素;(2)multiset允许容器中有重复的元素;
6.2 set 构造和赋值---创建set容器以及赋值
6.3 set 大小和交换
6.4 set 插入和删除
6.5 set 查找和统计
6.6 set和multiset的区别
(1)set不可以插入重复数据,而multiset可以;
(2)set插入数据的同时会返回插入结果,表示插入是否成功;
(3)multiset不会检测数据,因此可以插入重复数据;
//------------练习2:set(二叉树)容器练习---------
void PrintSet(const set<int>& s)
{
for(set<int>::const_iterator it=s.begin();it!=s.end();it++)
{
cout<<(*it)<<endl;
}
}
void PrintMultiSet(const multiset<int>& ms)
{
for(multiset<int>::iterator it=ms.begin();it!=ms.end();it++)
{
cout<<(*it)<<endl;
}
}
void test()
{
set<int>s;
pair<set<int>::iterator,bool>ret=s.insert(10);//返回对组数据类型
PrintSet(s);
if(ret.second)
cout<<"第一次插入成功!"<<endl;
else
cout<<"第一次插入失败!"<<endl;
ret=s.insert(10);
if(ret.second)
cout<<"第二次插入成功!"<<endl;
else
cout<<"第二次插入失败!"<<endl;
multiset<int>ms;
ms.insert(10);
ms.insert(10);
PrintMultiSet(ms);
}
int main()
{
test();
return 0;
}
6.7 pair对组创建---成对出现的数据,利用对组可以返回两个数据
pair<string,int>p1=make_pair("Jerry",30);
cout<<"姓名:"<<p1.first<<" 年龄:"<<p1.second<<endl;
6.8 set容器排序
set容器默认排序规则为从小到大,利用仿函数,可以改变排序规则;
//--------------练习3:set容器排序--------------
//(1)内置数据类型排序
class MySort
{
public:
bool operator()(int v1,int v2)//重载()
{
return v1>v2;//修改为降序
}
};
void test01()
{
set<int>s1;//默认为从小到大,升序排列
s1.insert(20);
s1.insert(30);
s1.insert(10);
s1.insert(70);
s1.insert(0);
for(set<int>::iterator it=s1.begin();it!=s1.end();it++)
{
cout<<(*it)<<" ";
}
cout<<endl;
//修改为降序,必须在插入数据之前进行设置
set<int,MySort>s2;//<>只能放数据类型,不可以放函数名,因此创建类
s2.insert(2);
s2.insert(3);
s2.insert(1);
s2.insert(7);
s2.insert(10);
for(set<int,MySort>::iterator it=s2.begin();it!=s2.end();it++)
{
cout<<(*it)<<" ";
}
cout<<endl;
}
//(2)自定义数据类型,都会制定排序规则,否则不知道怎么插入数据
class Person
{
public:
Person(string name,int age)
{
this->m_Name=name;
this->m_Age=age;
}
string m_Name;
int m_Age;
};
class MySort02
{
public:
bool operator()(const Person&P1,const Person&P2)
{
return P1.m_Age>P2.m_Age;
}
};
void test02()
{
Person P1("aaa",24);
Person P2("aaa",22);
Person P3("aaa",20);
Person P4("aaa",28);
set<Person,MySort02>s;
s.insert(P1);
s.insert(P2);
s.insert(P3);
s.insert(P4);
for(set<Person>::iterator it=s.begin();it!=s.end();it++)
{
cout<<"姓名:"<<(*it).m_Name<<" 年龄:"<<it->m_Age<<endl;
}
cout<<endl;
}
int main()
{
//test01();//内置数据类型修改排序
test02();//自定义数据类型
return 0;
}
7 map/multimap容器
7.1 map概念
(1)map中所有元素都是pair;(2)所有元素都会根据元素的键值自动排序;
(3)pair中的第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
本质:map/multimap属于关联式容器,底层结构是用二叉树实现。
优点:可以根据Key值快速找到value值;
map和multimap的区别:(1)map不允许容器中有重复的Key值元素;
(2)multimap允许容器中有重复的Key值元素
7.2 map容器 构造和赋值
//---------------练习4:map容器构造赋值-----------
void PrintMap(const map<int,int>&m)
{
for(map<int,int>::const_iterator it=m.begin();it!=m.end();it++)
{
cout<<"Key为:"<<(*it).first<<" 实值:"<<it->second<<endl;
}
}
void test()
{
//默认构造
map<int,int>m;//创建Map容器,数据要是对组形式,键值+实值
m.insert(pair<int,int>(2,10));//pair构造,匿名对象直接插入后注销
m.insert(pair<int,int>(5,10));//插入时会自动按key排序
m.insert(pair<int,int>(1,10));
m.insert(pair<int,int>(7,10));
PrintMap(m);
//拷贝构造
map<int,int>m2(m);
PrintMap(m2);
//赋值
map<int,int>m3;
m3=m2;
PrintMap(m3);
}
int main()
{
test();
return 0;
}
总结:map中所有元素都是成对出现,插入数据时候要是用对组;
7.3 map大小和交换
7.4 map容器-插入和删除
注意:这个elem要是对组形式
m.insert(pair<int,int>(1,10));//第一种
m.insert(make_pair(2,20));//第二种-----------------推荐!!
m.inset(map<int,int>::value_type(3,30));//第三种
m[4]=40;//第四种---不建议插入使用,但是可以利用Key访问到value,m[2]
7.5 map容器-查找和统计
//---------------练习5:map容器的查找和统计---------
void test()
{
map<int,int>m;
m.insert(make_pair(1,20));
m.insert(make_pair(2,30));
m.insert(make_pair(3,40));
for(map<int,int>::iterator it=m.begin();it!=m.end();it++)
{
cout<<"键值:"<<(*it).first<<" 实值:"<<it->second<<endl;
}
map<int,int>::iterator pos=m.find(3);//返回迭代器!!
if(pos!=m.end())
cout<<"找到"<<(*pos).first<<" "<<pos->second<<endl;//根据返回的迭代器找键值和实值
else
cout<<"找不到"<<endl;
cout<<"键值为2的元素个数"<<m.count(2)<<endl;
}
int main()
{
test();
return 0;
}
7.6 map容器-排序(默认从小到大,升序)---利用仿函数,改变排序规则
8 案例---员工分组
//案例描述
/*
公司今天招聘了10个员工(ABCDEFGHIJ),10名员工进入公司之后,需要指派员工在那个部门工作
员工信息有:姓名、工资组成;部门有:策划、美术、研发
随机给10名员工分配部门和工资
通过multimap进行信息的插入 key(部门编号)vlaue(员工)
分部门显示员工信息
*/
//实现步骤
/*
1、创建10名员工,放到vector中
2、遍历vector容器,取出每个员工,进行随机分组
3、分组后,将员工部门编号作为key,具体员工工作为value,放入到Multimap容器中
4、分部门显示员工信息
*/
class Worker
{
public:
/*Worker(string name,int salary)
{
this->m_Name=name;
this->m_Salary=salary;
}*/
string m_Name;
int m_Salary;
};
void CreateWorker(vector<Worker>& v)
{
string seed="ABCDEFGHIJ";
for(int i=0;i<10;i++)
{
Worker W;
W.m_Name=seed[i];
W.m_Salary=rand()%10000+10000;
v.push_back(W);
}
}
void ShowVector(const vector<Worker>&v)
{
for(vector<Worker>::const_iterator it=v.begin();it!=v.end();it++)
{
cout<<"员工姓名:"<<it->m_Name<<" 员工工资:"<<it->m_Salary<<endl;
}
}
void DepartWorker(vector<Worker>&v,multimap<int,Worker>&m)
{
for(vector<Worker>::iterator it=v.begin();it!=v.end();it++)
{
int ret=rand()%3;
m.insert(make_pair(ret,(*it)));
}
}
void PrintMap(const multimap<int,Worker>&m)
{
//策划
multimap<int,Worker>::const_iterator pos=m.find(SCHEME);//返回迭代器
int num=0;
int count=m.count(SCHEME);
cout<<"策划部门:"<<endl;
for(;pos!=m.end() && num<count;pos++,num++)
{
cout<<"员工姓名:"<<pos->second.m_Name<<" 员工工资:"<<pos->second.m_Salary<<endl;
}
//美术
pos=m.find(ART);//返回迭代器
count=m.count(ART);
cout<<"美术部门:"<<endl;
for(num=0;pos!=m.end() && num<count;pos++,num++)
{
cout<<"员工姓名:"<<pos->second.m_Name<<" 员工工资:"<<pos->second.m_Salary<<endl;
}
//研发
pos=m.find(TECH);//返回迭代器
count=m.count(TECH);
cout<<"研发部门:"<<endl;
for(num=0;pos!=m.end() && num<count;pos++,num++)
{
cout<<"员工姓名:"<<pos->second.m_Name<<" 员工工资:"<<pos->second.m_Salary<<endl;
}
}
int main()
{
srand((unsigned int)time(NULL));
//1、创建员工,放入vector中
vector<Worker>v;
CreateWorker(v);
//测试
//ShowVector(v);
//2、遍历vector容器,取出每个员工,进行随机分组
multimap<int,Worker>m;
DepartWorker(v,m);
//3、分部门显示员工信息
PrintMap(m);
return 0;
}