[第九天】C++的string类以STL标准模板库(万字详细解说)

一、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);//过大补30cout<<"大小:"<<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个元素2printVectorInt(v);v.pop_back();//尾部删除printVectorInt(v);v.erase(v.begin()+1,v.begin()+4);//删除三个2printVectorInt(v);v.clear();//大小清0cout<<"大小:"<<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 == Personcout<<(*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);//删除所有10l.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=Personcout<<"请输入"<<(*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查找对应的 用户。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/499548.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL 逗号分隔查询--find_in_set()函数

业务场景&#xff1a; 在使用MySQL的时候&#xff0c;可能的某个字段存储的是一个英文逗号分割的字符串&#xff08;这里我们不讨论表设计的合理性&#xff09;&#xff0c;如图所示&#xff1a; 我们在查询的时候需要匹配逗号分割中的某个字符串&#xff0c;该怎么查询呢&am…

压缩式 交换式 碎片整理 :(使碎片减少或没有)

交换式碎片整理 首先流程 是 p3这个程序在运行&#xff0c;p1p2p4 的话在等待 &#xff0c;然后p3这时要多用3个内存块&#xff0c;这是 p4 通过拷贝&#xff0c;将内存拷贝到磁盘上&#xff0c;对应的数据也是从主存中cp到磁盘此时主存多出3个内存块给p3继续使用 2.压缩式碎片…

手撕LRU缓存——LinkedHashMap简易源码

题目链接&#xff1a;https://leetcode.cn/problems/lru-cache/description/?envTypestudy-plan-v2&envIdtop-100-liked 原理非常简单&#xff0c;一个双端链表配上一个hash表。 首先我们要知道什么是LRU就是最小使用淘汰。怎么淘汰&#xff0c;链表尾部就是最不常用的直接…

vue3批量创建svg icon组件

1、通过插件动态导入svg文件 安装vite插件vite-plugin-svg-icons npm i vite-plugin-svg-icons -D 配置插件svg-icon.ts import { createSvgIconsPlugin } from "vite-plugin-svg-icons"; import path from "path";export default function createSvgI…

好物周刊#42:国产项目管理软件

https://github.com/cunyu1943 村雨遥的好物周刊&#xff0c;记录每周看到的有价值的信息&#xff0c;主要针对计算机领域&#xff0c;每周五发布。 一、项目 1. 菠萝博客 基于 Java 的菠萝博客系统&#xff0c;简单易部署&#xff0c;精致主题&#xff0c;贴心服务&#xf…

模型优化_XGBOOST学习曲线及改进,泛化误差

代码 from xgboost import XGBRegressor as XGBR from sklearn.ensemble import RandomForestRegressor as RFR from sklearn.linear_model import LinearRegression as LR from sklearn.datasets import load_boston from sklearn.model_selection import train_test_split,c…

ChatGPT提示词工程师AI大神吴恩达2023年视频课程学习实践

前言 刚才看了一个视频系列教程&#xff0c;很短&#xff0c;但收获很大&#xff0c;毕竟是一手知识来源&#xff0c;吴恩达大神亲自讲解&#xff0c;他说的话&#xff0c;我都信。这里写个笔记&#xff0c;顺便把知识点实践一下。视频可以去B站上搜索 吴恩达 prompt &#xf…

上门服务系统|上门服务小程序节省时间的必选利器

在如今的快节奏时代&#xff0c;我们的时间越来越宝贵。为了省时省力&#xff0c;越来越多的人选择使用上门服务类小程序。那么&#xff0c;为什么这些小程序能够如此受人欢迎呢&#xff1f;让我们一起揭示其中的原因。 一、方便快捷 上门服务类小程序最大的特点就是方便快捷。…

【探索AI】探索未来-计算机专业必看的几部电影

计算机专业必看的几部电影 计算机专业必看的几部电影&#xff0c;就像一场精彩的编程盛宴&#xff01;《黑客帝国》让你穿越虚拟世界&#xff0c;感受高科技的魅力&#xff1b;《社交网络》揭示了互联网巨头的创业之路&#xff0c;《源代码》带你穿越时间解救世界&#xff0c;…

Zabbix企业运维监控工具

Zabbix企业级监控方案 常见监控软件介绍 Cacti Cacti是一套基于 PHP、MySQL、SNMP 及 RRD Tool 开发的监测图形分析工具&#xff0c;Cacti 是使用轮询的方式由主服务器向设备发送数据请求来获取设备上状态数据信息的,如果设备不断增多,这个轮询的过程就非常的耗时&#xff0…

【驱动】TI AM437x(USB-01):USB Functionfs使用

1、内核、设备树配置USB Functionfs 1.1、配置内核 1)清理 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean2)生成配置文件.config make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- tisdk_am437x-evm_defconfig3)查看、修改配置项 make ARCH=arm CROSS…

Unity UI适配规则和对热门游戏适配策略的拆解

前言 本文会介绍一些关于UI适配的基础概念&#xff0c;并且统计了市面上常见的设备的分辨率的情况。同时通过拆解目前市面上较为成功的两款休闲游戏Royal Match和Monopoly GO(两款均为近期游戏付费榜前几的游戏)&#xff0c;大致推断出他们的适配策略&#xff0c;以供学习和参…