目录
编辑 8、 string和c风格(c-style)字符串转换
一、STL的概述
为提高复用性,建立数据结构和算法的一套标准,诞生了STL(Standard Template Library,标准模板库),STL从广义上分为三大组件:容器(container)、算法(algorithm)、迭代器(iterator),容器和算法之间通过迭代器进行无缝连接。.STL几乎所有的代码都采用.模板类或者模板函数,这相比传统的由函数和类组成的库来说提供了更好的代码重用机会。
STL的6大组件:
- 容器:存放数据
- 算法:操作数据
- 迭代器:算法和容器的桥梁,每个容器对应一个迭代器,算法 通过迭代器 操作 容器
- 适配器:为算法 提供更多的接口
- 仿函数:为算法 提供策略
- 空间配置:为算法、容器提供动态空间
算法分类:
- 质变算法:是指运算过程中会更改区间内的元素的内容(会更改容器的值),例如拷贝,替换,删除等等
- 非质变算法:是指运算过程中不会更改区间内的元素内容,例如查找、计数、遍历、寻 找极值等等
二、string容器(类)
C++标准库定义了一种string类,定义在头文件。String封装了很多实用的成员方法:查找find,搓贝copy,册除delete,替换replace,插入insert,不用考虑内存释放和越界。
1、构造函数以及赋值函数
string 构造函数
- string();//创建一个空的字符串 例如: string str;
- string(const string& str);//使用一个string对象初始化另一个string对象
- string(const char* s);//使用字符串s初始化
- string(int n, char c);//使用n个字符c初始化
string基本赋值操作函数
- string& operator=(const char* s);//char*类型字符串 赋值给当前的字符串
- string& operator=(const string &s);//把字符串s赋给当前的字符串
- string& operator=(char c);//字符赋值给当前的字符串
- string& assign(const char *s);//把字符串s赋给当前的字符串
- string& assign(const char *s, int n);//把字符串s的前n个字符赋给当前的字符串
- string& assign(const string &s);//把字符串s赋给当前字符串
- string& assign(int n, char c);//用n个字符c赋给当前字符串
- string& assign(const string &s, int start, int n);//将s从start开始n个字符 赋值给字符串
2、存取字符操作
char& operator[](int n);//通过[]方式获取字符
char& at(int n);//通过at方法获取字符
3、拼接操作
- string& operator+=(const string& str);//重载+=操作符
- string& operator+=(const char* str);//重载+=操作符
- string& operator+=(const char c);//重载+=操作符
- string& append(const string &s);//同operator+=()
- string& append(const char *s);//把字符串s连接到当前字符串结尾
- string& append(int n, char c);//在当前字符串结尾添加n个字符c
- string& append(const char *s, int n);//把字符串s的前n个字符连接到当前字符串 结尾
- string& append(const string &s, int pos, int n);//把字符串s中从pos开始的n个 字符连接到当前字符串结尾
4、查找和替换
利用string类中find、rfind和repace函数,注pos为缺省参数。
int find(const string& str, int pos = 0) const; //查找str第一次出现位置,从p os开始查找
int find(const char* s, int pos = 0) const; //查找s第一次出现位置,从pos开 始查找
int find(const char* s, int pos, int n) const; //从pos位置查找s的前n个字符 第一次位置
int find(const char c, int pos = 0) const; //查找字符c第一次出现位置
int rfind(const string& str, int pos = npos) const;//查找str最后一次位置,从 pos开始查找
int rfind(const char* s, int pos = npos) const;//查找s最后一次出现位置,从po s开始查找
int rfind(const char* s, int pos, int n) const;//从pos查找s的前n个字符最后 一次位置
int rfind(const char c, int pos = 0) const; //查找字符c最后一次出现位置
string& replace(int pos, int n, const string& str); //替换从pos开始n个字符 为字符串str 10 string& replace(int pos, int n, const char* s); //替换从pos开始的n个字符为 字符串s
5、比较操作
> < == != 运算符 可用。
compare函数在>时返回 1,<时返回 ‐1,==时返回 0。
int compare(const string &s) const;//与字符串s比较
int compare(const char *s) const;//与字符串s比较
6、提取子串
string substr(int pos = 0, int n = npos) const;//返回由pos开始的n个字符组成 的字符串
7、插入和删除操作
string& insert(int pos, const char* s); //插入字符串
string& insert(int pos, const string& str); //插入字符串
string& insert(int pos, int n, char c);//在指定位置插入n个字符c
string& erase(int pos, int n = npos);//删除从Pos开始的n个字符
8、 string和c风格(c-style)字符串转换
三、vector容器(类模板)
1、概述
vector容器:单端动态数组容器。必须包含头文件:#include<vector>
vector的数据安排以及操作方式,与array非常相似,两者的唯一差别在于空间的运用的灵活性。Array是静态空间,配置后再改变空间复杂,Vector是动态空间,随着元素的加入,它的内部机制会自动扩充空间以容纳新元素。
push_back尾部插入元素、pop_back尾部删除元素
front()头元素、back()尾元素
begin()得到的是 容器的 起始迭代器(首元素的位置)
end() 得到的是 结束迭代器(尾元素的下一个元素位置)
iterator迭代器 size()容器中元素的个数 capacity()容器的容量
一旦容量满载,下次再有新增元素,整个vector容器需另外开辟空间。为了降低空间配置时的速度成本,vector实际配置的大小可能比客户端需求大一些,以备将来可能的扩充。
2、相关API
构造函数:
- vector<T> v;//采用模版实现,默认构造函数
- vector(v.begin(), v.end());//将v[ begin(), end()]区间中的元素拷贝给本身
- vector(n, elem);//构造函数将n个elem拷贝给本身。
- vector(const vector &vec);//接贝构造函数。
赋值操作:
- assign(beg,end);//将[ beg,end)区间中的数据拷贝赋值给本身。
- assign(n,elem);//将n个elem拷贝赋值给本身。
- vector& operator=( const vector &vec);//重载等号操作符
- swap(vec);//将vec与本身的元素互换
大小操作:
- size();//返回容器中元素的个数。
- empty();//判断容器是否为空
- resize(int num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置,如果容器变短,则末尾超出容器长度的示素被删除。
- capacity();//容器的容量
- reserve(int len);//容器预留len个元素长度,但预留位置不初始化,元素不可访问。
存取操作:
- at(int idx);//返返回索引 idx所指的数据,如果idx越界,抛出out of range异常。
- operator[];返回索引idx所指的数据,越界时,运行直接报错
- front();//返回容器第一个元素
- back();//返回容器中最后一个数据元素
插入和删除:
- insert(const iterator pos,int count,ele);//迭代器指位置pos插入count个元素ele
- push_back(ele);//尾部插入元素ele
- pop_back();//删除最后一个元素
- erase(const_iterator start,const_iterator end);//删除迭代器从start到end之间的元素
- erase(const_iterator pos);/ /删除迭代器指向的元素
- clear();//删除容器中所有元素
举例说明:
//打印
void printVectorInt(vector<int> &v)
{
vector<int>::iterator it;
for(it=v.begin();it!=v.end();it++)
{
cout<<*it<<" ";
}
cout<<endl;
}
void test()
{
//构造
vector<int> v1(5,10);
printVectorInt(v1);
vector<int> v2=v1;//拷贝构造
printVectorInt(v2);
vector<int> v3(v1.begin(),v1.end());
printVectorInt(v3);
//赋值
vector<int> v4;
//v4=v3;----=运算符重载
v4.assign(v3.begin(),v3.end());
printVectorInt(v4);
v4.assign(5,100);
printVectorInt(v4);
//交换
v3.swap(v4);
printVectorInt(v3);
printVectorInt(v4);
//判断容器是否为空
vector<int> v5;
if(v5.empty())
{
cout<<"空"<<endl;
}
else
{
cout<<"非空"<<endl;
}
///重新指定容器的长度
vector<int> v6(10,20);
cout<<"大小:"<<v6.size()<<"容量:"<<v6.capacity()<<endl;
printVectorInt(v6);
v6.resize(15);//过大补零
//v6.resize(15,30);//过大补30
cout<<"大小:"<<v6.size()<<"容量:"<<v6.capacity()<<endl;
printVectorInt(v6);
v6.resize(10);//容量不变
cout<<"大小:"<<v6.size()<<"容量:"<<v6.capacity()<<endl;
printVectorInt(v6);
//存取
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.at(0)=10;v[1]=20;//可直接赋值
printVectorInt(v);
//at越界会抛出异常,[]越界不会抛出异常
cout<<v.at(0)<<" "<<v[0]<<endl;
cout<<"头元素:"<<v.front()<<"尾元素:"<<v.back()<<endl;
//插入和删除
v.insert(v.begin()+1,3,2);//迭代器指位置pos+1插入3个元素2
printVectorInt(v);
v.pop_back();//尾部删除
printVectorInt(v);
v.erase(v.begin()+1,v.begin()+4);//删除三个2
printVectorInt(v);
v.clear();//大小清0
cout<<"大小:"<<v.size()<<"容量:"<<v.capacity()<<endl;
}
运行结果:
3、巧用swap收缩空间
4、vector容器 嵌套 容器
5、使用算法 对 vector容器排序
#include <iostream>
#include<vector>
#include<algorithm>
using namespace std;
void printVectorInt(vector<int> &v)
{
vector<int>::iterator it;
for(it=v.begin(); it!=v.end();it++)
{
cout<<*it<<" ";
}
cout<<endl;
}
bool myCompare(int value1,int value2)
{
return value1>value2;
}
void test()
{
vector<int> v;
v.push_back(1);
v.push_back(6);
v.push_back(3);
v.push_back(9);
v.push_back(2);
printVectorInt(v);
//顺序
sort(v.begin(),v.end());
printVectorInt(v);
//倒序
//sort(v.begin(),v.end(), greater<int>());
//sort(v1.begin(), v1.end(), myCompare);
}
int main(int argc, char *argv[])
{
test();
return 0;
}
6、vector存放自定义数据类型
class Person
{
friend void printVectorPerson(vector<Person> &v);
friend bool myComparePerson(const Person &ob1, const Person &ob2);
private:
int num;
string name;
float score;
public:
Person(){}
Person(int num, string name, float score)
{
this‐>num = num;
this‐>name = name;
this‐>score = score;
}
#if 0
//方法2:重载自定义数据的<运算符
bool operator<(const Person &ob)
{
return this‐>num < ob.num;
}
#endif
};
void printVectorPerson(vector<Person> &v)
{
vector<Person>::iterator it;
for(it=v.begin(); it!=v.end(); it++)
{
//*it == Person
cout<<(*it).num<<" "<<(*it).name<<" "<<(*it).score<<endl;
}
}
//方法1:对于自定义容器排序 必须实现 排序规则
bool myComparePerson(const Person &ob1, const Person &ob2)
{
if(ob1.num == ob2.num)
return ob1.score>ob2.score;
return ob1.num > ob2.num;
}
void test()
{
vector<Person> v;
v.push_back(Person(1, "lucy", 88.5f));
v.push_back(Person(3, "tom", 77.5f));
v.push_back(Person(3, "小明", 85.5f));
v.push_back(Person(2, "小红", 96.5f));
printVectorPerson(v);
//方法1:对于自定义容器排序 必须实现 排序规则
sort(v.begin(), v.end(), myComparePerson);
//方法2:重载自定义数据的<运算符
//sort(v.begin(), v.end());
cout<<"‐‐‐‐‐‐‐‐‐‐‐‐‐‐"<<endl;
printVectorPerson(v);
}
四、deque容器
1、deque的概述
deque:双端动态数组
Deque容器和vector容器的区别:
1、deque允许使用常数项时间对头端进行元素的插入和删除操作。
2、deque没有容量的概念。
无容量概念是因为它是动态的以分段连续空间组合而成,随时可以增加一段新的空间并链接起来,不会像vector那样”旧空间不足而重新配置一块更大空间,然后复制元素,再释放旧空间"。也因此,deque没有必须要提供所谓的空间保留(reserve)功能。
2、deque的API
构造函数:
- deque<T> deqT;//采用模版实现,默认构造函数
- deque(v.begin(), v.end());//将v[ begin(), end()]区间中的元素拷贝给本身
- deque(n, elem);//构造函数将n个elem拷贝给本身。
- deque(const vector &deq);//接贝构造函数。
赋值操作:
- assign(beg,end);//将[ beg,end)区间中的数据拷贝赋值给本身。
- assign(n,elem);//将n个elem拷贝赋值给本身。
- deque& operator=( const deque &vec);//重载等号操作符
- swap(deq);//将vec与本身的元素互换
大小操作:
- size();//返回容器中元素的个数。
- empty();//判断容器是否为空
- resize(int num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置,如果容器变短,则末尾超出容器长度的示素被删除。
- deque.resize(num, elem); //重新指定容器的长度为num,若容器变长,则以elem值填 充新位置,如果容器变短,则末尾超出容器长度的元素被删除
存取操作:
- at(int idx);//返返回索引 idx所指的数据,如果idx越界,抛出out of range异常。
- operator[];返回索引idx所指的数据,越界时,运行直接报错
- front();//返回容器第一个元素
- back();//返回容器中最后一个数据元素
双端插入删除:
- push_front(elem);//在容器头部插入一个数据
- push_back(ele);//尾部插入元素ele
- pop_front();//删除容器第一个数据
- pop_back();//删除最后一个元素
插入和删除:
- insert(const iterator pos,int count,ele);//迭代器指位置pos插入count个元素ele
- insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值
- insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值
- erase(const_iterator start,const_iterator end);//删除迭代器从start到end之间的元素
- erase(const_iterator pos);/ /删除迭代器指向的元素
- clear();//删除容器中所有元素
如果迭代器能+X 那么该迭代器 为随机访问迭代器
vector存放的数据 没有多大规律,只是纪录数据。
deque容器:用于类似竞技的数据
3、deque容器的案例
有5名选手:选手ABCDE,10个评委分别对每一名选手打分,去除最高分,去除评委中 最低分,取平均分。
1. 创建五名选手,放到vector中
2. 遍历vector容器,取出来每一个选手,执行for循环,可以把10个评分打分存到deque 容器中
3. sort算法对deque容器中分数排序,pop_back pop_front去除最高和最低分
4. deque容器遍历一遍,累加分数,累加分数/d.size()
5. person.score = 平均分
#include<vector>
class Player
{
public:
string name;
float score;
public:
Player(){}
Player(string name,float score=0.0f)//缺省参数
{
this‐>name = name;
this‐>score=score;
}
};
void createPlayer(vector<Player> &v)
{
string seedName = "ABCDE";
int i=0;
for(i=0;i<5;i++)
{
string tmpName = "选手";
tmpName+=seedName[i];
v.push_back(Player(tmpName));//Player(tmpName)为匿名对象
}
}
#include<stdlib.h>
#include<time.h>
#include<algorithm>
void playGame(vector<Player> &v)
{
//设置随机数 种子
srand(time(NULL));
//每名选手都要参加
vector<Player>::iterator it;
for(it=v.begin(); it!=v.end();it++)
{
//10个评委打分
deque<float> d;
int i=0;
for(i=0;i<10;i++)
{
d.push_back(rand()%41+60);
}
// 对d容器排序
sort(d.begin(),d.end());
//去掉最高分
d.pop_back();
//去掉最低分
d.pop_front();
//求总分数
(*it).score = accumulate(d.begin(),d.end(), 0)/d.size();
}
}
void showScore(vector<Player> &v)
{
vector<Player>::iterator it;
for(it=v.begin(); it!=v.end();it++)
{
cout<<(*it).name<<"所得分数:"<<(*it).score<<endl;
}
}
void test()
{
//创建5名选手 放入vector容器中
vector<Player> v;
createPlayer(v);
//开始比赛
playGame(v);
//公布成绩
showScore(v);
}
五、stack栈容器
1、stack的概述
stack是一种先进后出(First In Last Out,FILO)的数据结构。它只有一个栈顶出口,但是除了栈顶外,没有任何其他方法可以存取stack 的其他元素。换言之,stack不允许有遍历行为。有元素推入栈的操作称为:push,将元素推出stack 的操作称为pop。
注:
操作数据的一端的顶部叫栈顶。
top永远指向栈顶元素。
栈容器没有迭代器。不支持遍历行为。
2、stack的API
stack构造函数:
- stack<int> T;//stack采用模板类实现, stack对象的默认构造形式
- stack(const stack &stk);//拷贝构造函数
stack赋值操作:
- stack& operator=(const stack &stk);//重载等号操作符
stack数据存取操作:
- push(elem);//向栈顶添加元素
- pop();//从栈顶移除第一个元素
- top();//返回栈顶元素
stack大小操作:
- empty();//判断堆栈是否为空
- size();//返回堆栈的大小
六、queue队列容器
Queue是一种先进先出(First In First Out,FIFO)的数据结构,它有两个出口。
出数据的一方叫队头,入数据的一方叫队尾。
queue容器没有迭代器 不支持遍历行为。
queue构造函数:
- queue<int> queT;//stack采用模板类实现, queue对象的默认构造形式
- queue(const stack &stk);//拷贝构造函数
queue赋值操作:
- queue& operator=(const stack &stk);//重载等号操作符
queue数据存取操作:
- push(elem);///往队尾添加元素
- pop();//从栈顶移除第一个元素
- back();//返回最后一个元素
- front();//返回第一个元素
queue大小操作:
- empty();//判断堆栈是否为空
- size();//返回堆栈的大小
七、list链表容器
list为双向循环链表,迭代器是 双向迭代器。
构造函数:
- list<T> lstT;//采用模版实现,默认构造函数
- list(v.begin(), v.end());//将v[ begin(), end()]区间中的元素拷贝给本身
- list(n, elem);//构造函数将n个elem拷贝给本身。
- list(const vector &deq);//接贝构造函数。
赋值操作:
- assign(beg,end);//将[ beg,end)区间中的数据拷贝赋值给本身。
- assign(n,elem);//将n个elem拷贝赋值给本身。
- deque& operator=( const deque &vec);//重载等号操作符
- swap(deq);//将vec与本身的元素互换
大小操作:
- size();//返回容器中元素的个数。
- empty();//判断容器是否为空
- resize(int num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置,如果容器变短,则末尾超出容器长度的示素被删除。
- deque.resize(num, elem); //重新指定容器的长度为num,若容器变长,则以elem值填 充新位置,如果容器变短,则末尾超出容器长度的元素被删除
存取操作:
- front();//返回容器第一个元素
- back();//返回容器中最后一个数据元素
双端插入删除:
- push_front(elem);//在容器头部插入一个数据
- push_back(ele);//尾部插入元素ele
- pop_front();//删除容器第一个数据
- pop_back();//删除最后一个元素
插入和删除:
- insert(const iterator pos,ele);//迭代器指位置pos插入元素ele
- insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值
- insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值
- erase(const_iterator start,const_iterator end);//删除迭代器从start到end之间的元素
- erase(const_iterator pos);/ /删除迭代器指向的元素
- remove(elem);//删除容器中所有与elem值匹配的元素。
- clear();//删除容器中所有元素
反转排序:
- reverse();//反转链表
- sort(); //list排序
#include<iostream>
#include<list>
#include<algorithm>
using namespace std;
void printListInt(list<int> &l)
{
list<int>::iterator it;
for(it=l.begin();it!=l.end();it++)
{
cout<<*it<<" ";
}
cout<<endl;
}
void test()
{
list<int> l;
l.push_front(1);
l.push_front(2);
l.push_front(3);
l.push_back(4);
l.push_back(5);
l.push_back(6);
printListInt(l);
//list容器 是双向迭代器 不支持+X 支持++
//不支持l.insert(l.begin()+2,3,10);
list<int>::iterator it=l.begin();
it++;
it++;
l.insert(it,3,10);
printListInt(l);
//删除所有10
l.remove(10);
printListInt(l);
//排序
//STL提供的算法 只支持 随机访问迭代器,而list是双向迭代器 所以sort不支持list
//不支持sort(l.begin(),l.end());
l1.sort();
// l1.sort(greater<int>());//倒序
printListInt(l);
}
int main(int argc, char* argv[])
{
test();
return 0;
}
运行结果:
八、set/mulitset容器
1、set/mulitset的概述
set容器的特征是所有元素都会根据元素的键值自动被排序。Set 不允许两个元素。set的元素即是键值又是实值。,故不能通过set的迭代器改变set元素的值,会破坏set的数据结构。set容器的迭代器是只读迭代器const_iterator。
multiset特性及用法和set完全相同,唯一的差别在于它允许键值重复。set和multiset的底层实现是红黑树,红黑树为平衡二叉树的一种。树的简单知识:二叉树就是任何节点最多只允许有两个字节点。分别是左子结点和右子节点。
二叉搜索树,是指二叉树中的节点按照一定的规则进行排序,使得对二叉树中元素访问更加高效。二叉搜索树的放置规则是:任何节点的元素值一定大于其左子树中的每一个节点的元素值,并且小于其右子树的值。因此从根节点一直向左走,一直到无路可走,即得到最小值,一直向右走,直至无路可走,可得到最大值。那么在儿茶搜索树中找到最大元素和最小元素是非常简单的事情。
2、set/mulitset的API
set构造函数:
- set<int> st;//set默认构造函数:
- mulitset mst; //multiset默认构造函数:
- set(const stack &stk);//拷贝构造函数
set赋值操作:
- set& operator=(const stack &stk);//重载等号操作符
- swap(st);//交换两个集合容器
set插入和删除操作
- insert(elem);//在容器中插入元素。
- clear();//清除所有元素
- erase(pos);//删除pos迭代器所指的元素,返回下一个元素的迭代器。
- erase(beg, end);//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器
- erase(elem);//删除容器中值为elem的元素。
set大小操作:
- empty();//判断堆栈是否为空
- size();//返回堆栈的大小
set查找操作:
- find(key);//查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回se t.end();
- count(key);//查找键key的元素个数
- lower_bound(keyElem);//返回第一个key>=keyElem元素的迭代器。
- upper_bound(keyElem);//返回第一个key>keyElem元素的迭代器。
- equal_range(keyElem);//返回容器中key与keyElem相等的上下限的两个迭代器
查找元素的上下限:
用pair对组判断插入是否成功:
3、更改set容器的排序规则(定义set容器时 修改)
一般都是通过 “仿函数” 修改set容器的排序规则。
set<int,排序规则类> s1;
4、如果set容器存放自定义数据 必须更改排序规则
#include<iostream>
#include<set>
#include<algorithm>
using namespace std;
class Person
{
friend ostream& operator <<(ostream &out,Person s);
friend class myGraterPerson;
private:
int num;
string name;
float score;
public:
Person(){}
Person(int num,string name,float score )
{
this->name=name;
this->num=num;
this->score=score;
}
};
//仿函数
class myGraterPerson
{
public:
bool operator()(Person s1,Person s2)
{
return s1.num<s2.num;
}
};
ostream& operator <<(ostream &out,Person s)
{
out<<s.num<<" "<<s.name<<""<<s.score<<endl;
return out;
}
void printListPerson(set<Person,myGraterPerson> &s)
{
set<Person,myGraterPerson>::iterator it;
for(it=s.begin();it!=s.end();it++)
{
cout<<(*it);
}
cout<<endl;
}
void test()
{
set<Person,myGraterPerson> s;
s.insert(Person(4,"小红",85.5));
s.insert(Person(1,"小明",75.5));
s.insert(Person(3,"tom",87.5));
s.insert(Person(2,"lucy",82.5));
s.insert(Person(5,"bob",78.5));
printListPerson(s);
}
int main(int argc, char* argv[])
{
test();
return 0;
}
关键代码及运行结果:
5、multiset容器 键值可以重复
九、pair对组
对组(pair)将一对值组合成一个值,这一对值可以具有不同的数据类型,两个值 可以分别用pair的两个公有属性first和second访问。
十、map/multimap容器
1、概述
Map的特性是,所有元素都会根据元素的键值自动排序。Map 所有的元素都是pair,同时拥有实值和键值,pair的第一元素被视为键值,第二元素被视为实值,map不允许两个元素有相同的键值。不能通过map 的迭代器改变map 的键值。Multimap 和map的操作类似,唯一区别multimap键值可重复。底层实现机制是红黑树。
2、API
map构造函数:
- map<T1,T2> mapTT;//map默认构造函数:
- map(const map &mp);//拷贝构造函数
map赋值操作:
- map& operator=(const map &mp);//重载等号操作符
- swap(mp);//交换两个集合容器
map大小操作:
- empty();//判断堆栈是否为空
- size();//返回堆栈的大小
map插入操作
- map.insert(...); //往容器插入元素,返回pair<interator,bool>
- map<int,string> mapStu;
- //举例
- // 第一种 通过pair的方式插入对象
- mapStu.insert(pair<int,string>(1, "小红"));
- mapStu.inset(make_pair(2, "小明"));
- // 第二种 通过value_type的方式插入对象
- mapStu.insert(map<int,string>::value_type(3, "小李"));
- // 第四种 通过数组的方式插入值
- mapStu[1] = "小王";
- mapStu[3] = "小刘";
map删除操作:
- clear();//删除所有元素
- erase(pos);//删除pos迭代器所指的元素,返回下一个元素的迭代器。
- erase(beg,end);//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器
- erase(beg,end);//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器
map查找操作:
- find(key);//查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回se t.end();
- count(key);//查找键key的元素个数
- lower_bound(keyElem);//返回第一个key>=keyElem元素的迭代器。
- upper_bound(keyElem);//返回第一个key>keyElem元素的迭代器。
- equal_range(keyElem);//返回容器中key与keyElem相等的上下限的两个迭代器
案例:
#include<iostream>
#include<map>
using namespace std;
class Person
{
friend void test();
friend void printmapPerson(map<int,Person> &m);
private:
int num;
string name;
float score;
public:
Person(){}
Person(int num,string name,float score)
{
this->name=name;
this->num=num;
this->score=score;
}
};
void printmapPerson(map<int,Person> &m)
{
map<int,Person>::iterator it;
for(it=m.begin();it!=m.end();it++)
{
//*it==pair<int,Person>
cout<<"学号:"<<(*it).first<<" "<<"姓名:"<<(*it).second.name<<" \
分数:"<<(*it).second.score<<endl;
}
cout<<endl;
}
void test()
{
map<int,Person> m;
//插入方式1:
m.insert(pair<int,Person>(3, Person(3,"小红", 89.5f)));
m.insert(make_pair(1,Person(1,"小明", 87.5f)));//推荐使用
//插入方式2:
m.insert( map<int, Person>::value_type( 2 , Person(2,"tom",
66.6f)));
//插入方式3:
m[4] = Person(4,"小李", 92.5f);
printmapPerson(m);
//假如key值存在 m[key]代表对应的实值,若不存在,系统会重新创建。
cout<< m[7].num<<" "<<m[7].name<<" "<<m[7].score<<endl;
printmapPerson(m);
//删除元素
m.erase(4);
printmapPerson(m);
//查找元素对组
map<int, Person>::const_iterator ret;
ret=m.find(3);
if(ret!=m.end())
{
cout<<"找到该元素:"<< (*ret).first<<" "<<(*ret).second.name<<" "
<<(*ret).second.score<<endl;
}
}
int main(int argc, char* argv[])
{
test();
return 0;
}
main关键代码:
3、multimap实际案例
公司今天招聘了5个员工,5名员工进入公司之后,需要指派员工在那个部门工 作 人员信息有: 姓名 年龄 电话 工资等组成 通过Multimap进行信息的插入 保存 显示 分部门显示员工信息 显示全部员工信息。
#include<iostream>
#include<map>
#include<vector>
#include<time.h>
#include<stdlib.h>
using namespace std;
class Person
{
friend void showPartmentPerson(multimap<int,Person> &m);
friend void personJoinPartment(multimap<int,Person> &m,vector<Person> &v);
private:
string name;
int age;
string tel;
int salary;
public:
Person(){}
Person(string name,int age,string tel,int salary);
};
void personJoinPartment(multimap<int,Person> &m,vector<Person> &v);
void createVectorPerson(vector<Person> &v);
void showPartmentPerson(multimap<int,Person> &m);
void test()
{
//创建vector容器存放员工
vector<Person> v;
createVectorPerson(v);
//员工加入部门
multimap<int,Person> m;
personJoinPartment(m,v);
//显示部门成员
showPartmentPerson(m);
}
int main(int argc, char* argv[])
{
test();
return 0;
}
void createVectorPerson(vector<Person> &v)
{
//设置随机数种子
srand(time(NULL));
int i=0;
for(i=0;i<5;i++)
{
string seedname="ABCDE";
string tmpname="员工";
tmpname+=seedname[i];
int age=20+i;
string tel=to_string(rand());
int salary=10000+rand()%10*1000;
v.push_back(Person(tmpname,age,tel,salary));
}
}
void personJoinPartment(multimap<int,Person> &m,vector<Person> &v)
{
vector<Person>::iterator it;
for(it=v.begin();it!=v.end();it++)
{
//*it=Person
cout<<"请输入"<<(*it).name<<"要加入的部门:1(销售)、2(研发)、3(财务)";
int op;
cin>>op;
m.insert(make_pair(op,*it));
}
}
void showPartmentPerson(multimap<int,Person> &m)
{
cout<<"请输入"<<"要显示的部门:的部门1(销售)、2(研发)、3(财务)";
int op;
cin>>op;
switch (op) {
case 1:
cout<<"---销售部门---"<<endl;
break;
case 2:
cout<<"---研发部门---"<<endl;
break;
case 3:
cout<<"---财务部门---"<<endl;
break;
default:
break;
}
multimap<int,Person>::const_iterator ret;
ret=m.find(op);
int count=m.count(op);
for(int i=0;i<count;i++,ret++)
{
//*ret=pair<int, Person>
cout<<"\t"<<(*ret).second.name<<" "<<(*ret).second.age<<" "\
<<(*ret).second.salary<<" "<<(*ret).second.tel<<endl;
}
return;
}
Person::Person(string name, int age, string tel, int salary)
{
this->name=name;
this->age=age;
this->tel=tel;
this->salary=salary;
}
运行案例:
十一、容器的使用时机
vector的使用场景:比如软件历史操作记录的存储
deque的使用场景:比如排队购票系统,支持头端的快速移除,尾端的快速添加
list的使用场景:比如公交车乘客的存储,随时可能有乘客下车,支持频繁的不 确实位置元素的移除插入
set的使用场景:比如对手机游戏的个人得分记录的存储,存储要求从高分到低 分的顺序排列
map的使用场景:比如按ID号存储十万个用户,想要快速要通过ID查找对应的 用户。