C++标准模板库(STL)使用方法总结

1.vector容器使用方法

1.文件包含变量声明
使用vector容器需要包含头文件<vector>

vector容器的构造函数:
vector():创建一个空vector
vector(int nSize):创建一个vector,元素个数为nSize
vector(int nSize,const t& t):创建一个vector,元素个数为nSize,且值均为t
vector(const vector&):复制构造函数
vector(begin,end):复制[begin,end)区间内另一个数组的元素到vector中

vector容器初始化实例:

#include <vector>
#include <iostream>
using namespace std;
int main(){
   //int型vector  
   vector<int> vecInt;
     
   //float型vector  
   vector<float> vecFloat;
     
   //嵌套vector
   vector<vector<int>> vec;
  
  //结构体或类 类型的vector
  class A  
  {  
    //空类  
  };
  vector<A> vecA
  
  struct B
  {
    //空结构体
  }
  vector<B> vecB

}

2.函数调用

1. push_back()           在数组的最后添加一个数据
2. pop_back()            去掉数组的最后一个数据 
3. at()                  得到编号位置的数据
4. begin()              得到数组头的指针
5. end()                 得到数组的最后一个单元+1的指针
6front()               得到数组头的引用
7. back()                得到数组的最后一个单元的引用
8. max_size()            得到vector最大可以是多大
9. capacity()            当前vector分配的大小
10.size()                当前使用数据的大小
11.resize()              改变当前使用数据的大小,如果它比当前使用的大,者填充默认值
12.reserve()             改变当前vector所分配空间的大小
13.erase()               删除指针指向的数据项
14.clear()               清空当前的vector
15.rbegin()              将vector反转后的开始指针返回(其实就是原来的end-1)
16.rend()                将vector反转构的结束指针返回(其实就是原来的begin-1)
17.empty()               判断vector是否为空
18.swap()                与另一个vector交换数据

3.vector容器内存管理
(1) 使用reserve()函数提前设定容量大小,避免多次容量扩充操作导致效率低下。

假定你想建立一个容纳1-1000值的vector。没有使用reserve,你可以像这样来做:

vector<int> v;
for (int i = 1; i <= 1000; ++i)
   v.push_back(i);

在大多数STL实现中,这段代码在循环过程中将会导致2到10次重新分配。(vector在重新分配发生时一般把容量翻倍)

把代码改为使用reserve,在循环中不会发生重新分配:

vector<int> v;
v.reserve(1000);
for (int i = 1; i <= 1000; ++i) 
   v.push_back(i);

4.增加函数

void push_back(const T& x)//向量尾部增加一个元素X,使用vector函数添加数
//使用迭代器添加数
iterator insert(iterator it,const T& x) //向量中迭代器指向元素前增加一个元素x
iterator insert(iterator it,int n,const T& x) //向量中迭代器指向元素前增加n个相同的元素x
iterator insert(iterator it,const_iterator first,const_iterator last) //向量中迭代器指向元素前插入另一个相同类型向量的[first,last)间的数据

增加实例:

//push_back在尾部插入数字1
vector<int> vecIntA;
vecIntA.push_back(1);

//使用迭代器在第一个位置插入数值888
vector<int> vecIntB;
vector<int>::iterator it;
vecIntB.insert(it=vecIntB.begin(),888);

//使用迭代器在第一个位置前插入数值3个888
vector<int> vecIntC;
vector<int>::iterator it;
vecIntC.insert(it=vecIntC.begin(),3,888);

5.删除函数

iterator erase(iterator it) //删除向量中迭代器指向元素
iterator erase(iterator first,iterator last) //删除向量中[first,last)中元素
void pop_back() //删除向量中最后一个元素
void clear() //清空向量中所有元素

删除实例:

//删除最后一个元素  
vecIntA.pop_back();
  
//删除第四个位置的元素
vector<int> vecIntA;
vecIntA.erase(vecIntA.begin()+4);

//删除第2-5个元素  
vecIntA.erase(vecIntA.begin()+1,vecIntA.begin()+5);

6.修改vector容器中的数据
(1)通过数组修改

//修改第二个元素为8
vector<int> vecIntA;
vecIntA[1]=8;

(2)通过引用修改

//修改第二个元素为18
vector<int> vecIntA;
int &m = vecIntA.at(1);  
m=18;

(3)通过迭代器修改

//修改第二个元素为28
vector<int> vecIntA; 
vector<int>::iterator itr = vecIntA.begin()+1;  
*itr = 28;

7.输出vector容器中的内容
(1)

vector<int> vecIntA;
for(int i=0;i<vecIntA.size();i++)   
{  
        cout<<vecIntA[i]<<endl;  
}  

(2)

vector<int> vecIntA;
for(int i=0;i<vecIntA.size();i++)  
{  
        cout<<vecIntA.at(i)<<endl;  
}  

(3)

vector<int> vecIntA;
for(vector<int>::iterator it = vecIntA.begin();it!=vecIntA.end();it++)  
{  
        cout<<*it<<endl;  
}  

2.map/multimap使用方法

1.头文件

#include<map>

2.声明及其初始化

map<key, value> m;//创建一个名为m的空map对象,其键和值的类型分别为key和value。
map<key, value> m(m2);//创建m2的副本m,m与m2必须有相同的键类型和值类型。
map<key, value> m(b,e);//创建map类型的对象m,存储迭代器b和e标记的范围内所有元素的副本,元素的类型必须能转换为pair
map<key, value, comp> mp;//comp可选,为键值对存放策略,即键的比较函数,默认标准库使用键类型定义的 < 操作符来实现键的比较。所用的比较函数必须在键类型上定义严格的弱排序,可将其理解为键类型数据上的“小于”关系。在实际应用中,键类型必须能定义 < 操作符。对于键类型,其唯一的约束就是必须支持 < 操作符。

3.数据插入
第一种:用insert函数插入pair数据:

//数据的插入--第一种:用insert函数插入pair数据
#include <map>
#include <string>
#include <iostream>
using namespace std;
int main()
{
    map<int, string> mapStudent;
    mapStudent.insert(pair<int, string>(1, "student_one"));
    mapStudent.insert(pair<int, string>(2, "student_two"));
    mapStudent.insert(pair<int, string>(3, "student_three"));
    map<int, string>::iterator iter;
    for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
       cout<<iter->first<<' '<<iter->second<<endl;
}

第二种:用insert函数插入value_type数据:

//第二种:用insert函数插入value_type数据,下面举例说明
#include <map>
#include <string>
#include <iostream>
using namespace std;
int main()
{
    map<int, string> mapStudent;
    mapStudent.insert(map<int, string>::value_type (1, "student_one"));
    mapStudent.insert(map<int, string>::value_type (2, "student_two"));
    mapStudent.insert(map<int, string>::value_type (3, "student_three"));
    map<int, string>::iterator iter;
    for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
       cout<<iter->first<<' '<<iter->second<<endl;
}

第三种:用数组方式插入数据:

//第三种:用数组方式插入数据,下面举例说明
#include <map>
#include <string>
#include <iostream>
using namespace std;
int main()
{
    map<int, string> mapStudent;
    mapStudent[1] = "student_one";
    mapStudent[2] = "student_two";
    mapStudent[3] = "student_three";
    map<int, string>::iterator iter;
    for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
        cout<<iter->first<<' '<<iter->second<<endl;
}

以上三种用法,虽然都可以实现数据的插入,但是它们是有区别的,当然了第一种和第二种在效果上是完成一样的,用insert函数插入数据,在数据的 插入上涉及到集合的唯一性这个概念,即当map中有这个关键字时,insert操作是插入数据不了的,但是用数组方式就不同了,它可以覆盖以前该关键字对 应的值

4.数据遍历
第一种:应用前向迭代器,上面举例程序中已经体现,略。

第二种:应用反相迭代器。

//第二种,利用反向迭代器
#include <map>
#include <string>
#include <iostream>
using namespace std;
int main()
{
    map<int, string> mapStudent;
    mapStudent.insert(pair<int, string>(1, "student_one"));
    mapStudent.insert(pair<int, string>(2, "student_two"));
    mapStudent.insert(pair<int, string>(3, "student_three"));
    map<int, string>::reverse_iterator iter;
    for(iter = mapStudent.rbegin(); iter != mapStudent.rend(); iter++)
        cout<<iter->first<<"  "<<iter->second<<endl;
}

第三种,用数组的形式

//第三种:用数组方式,程序说明如下
#include <map>
#include <string>
#include <iostream>
using namespace std;
int main()
{
    map<int, string> mapStudent;
    mapStudent.insert(pair<int, string>(1, "student_one"));
    mapStudent.insert(pair<int, string>(2, "student_two"));
    mapStudent.insert(pair<int, string>(3, "student_three"));
    int nSize = mapStudent.size();
//此处应注意,应该是 for(int nindex = 1; nindex <= nSize; nindex++)
//而不是 for(int nindex = 0; nindex < nSize; nindex++)
    for(int nindex = 1; nindex <= nSize; nindex++)
        cout<<mapStudent[nindex]<<endl;
}

5.查找并获取map中的元素(包括判定这个关键字是否在map中出现)
第一种:用count函数来判定关键字是否出现,其缺点是无法定位数据出现位置,由于map的特性,一对一的映射关系,就决定了count函数的返回值只有两个,要么是0,要么是1,出现的情况,当然是返回1了。
第二种:用find函数来定位数据出现位置,它返回的一个迭代器,当数据出现时,它返回数据所在位置的迭代器,如果map中没有要查找的数据,它返回的迭代器等于end函数返回的迭代器。

查找map中是否包含某个关键字条目用find()方法,传入的参数是要查找的key,在这里需要提到的是begin()和end()两个成员,
分别代表map对象中第一个条目和最后一个条目,这两个数据的类型是iterator.

#include <map>
#include <string>
#include <iostream>
using namespace std;
int main()
{
    map<int, string> mapStudent;
    mapStudent.insert(pair<int, string>(1, "student_one"));
    mapStudent.insert(pair<int, string>(2, "student_two"));
    mapStudent.insert(pair<int, string>(3, "student_three"));
    map<int, string>::iterator iter;
    iter = mapStudent.find(1);
    if(iter != mapStudent.end())
       cout<<"Find, the value is "<<iter->second<<endl;
    else
       cout<<"Do not Find"<<endl;
    return 0;
}

第三种:这个方法用来判定数据是否出现
lower_bound函数用法,这个函数用来返回要查找关键字的下界(是一个迭代器)
upper_bound函数用法,这个函数用来返回要查找关键字的上界(是一个迭代器)

例如:map中已经插入了1,2,3,4的话,如果lower_bound(2)的话,返回的2,而upper-bound(2)的话,返回的就是3

#include <map>
#include <string>
#include <iostream>
using namespace std;
int main()
{
   map<int, string> mapStudent;
    mapStudent[1] = "student_one";
    mapStudent[3] = "student_three";
    mapStudent[5] = "student_five";
    map<int, string>::iterator iter;
    iter = mapStudent.lower_bound(1);
     //返回的是下界1的迭代器
        cout<<iter->second<<endl;
    iter = mapStudent.lower_bound(2);
    //返回的是下界3的迭代器
        cout<<iter->second<<endl;
    iter = mapStudent.lower_bound(3);
    //返回的是下界3的迭代器
        cout<<iter->second<<endl;
    iter = mapStudent.upper_bound(2);
    //返回的是上界3的迭代器
        cout<<iter->second<<endl;
    iter = mapStudent.upper_bound(3);
    //返回的是上界5的迭代器
        cout<<iter->second<<endl;
       pair<map<int, string>::iterator, map<int,string>::iterator> mappair;
    mappair = mapStudent.equal_range(2);
    if(mappair.first == mappair.second)
        cout<<"Do not Find"<<endl;
    else
        cout<<"Find"<<endl;
    mappair = mapStudent.equal_range(3);
    if(mappair.first == mappair.second)
        cout<<"Do not Find"<<endl;
    else
        cout<<"Find"<<endl;
    return 0;
}

6.从map中删除元素
移除某个map中某个条目用erase()

该成员方法的定义如下:
iterator erase(iterator it);//通过一个条目对象删除

iterator erase(iterator first,iterator last)//删除一个范围

size_type erase(const Key&key);//通过关键字删除

clear()就相当于enumMap.erase(enumMap.begin(),enumMap.end());

#include <map>
#include <string>
#include <iostream>
using namespace std;
int main()
{
       map<int, string> mapStudent;
       mapStudent.insert(pair<int, string>(1, "student_one"));
       mapStudent.insert(pair<int, string>(2, "student_two"));
       mapStudent.insert(pair<int, string>(3, "student_three"));
        //如果你要演示输出效果,请选择以下的一种,你看到的效果会比较好
       //如果要删除1,用迭代器删除
       map<int, string>::iterator iter;
       iter = mapStudent.find(1);
       mapStudent.erase(iter);
       //如果要删除1,用关键字删除
       int n = mapStudent.erase(1);//如果删除了会返回1,否则返回0
       //用迭代器,成片的删除
       //一下代码把整个map清空
       mapStudent.erase( mapStudent.begin(), mapStudent.end() );
       //成片删除要注意的是,也是STL的特性,删除区间是一个前闭后开的集合
       //自个加上遍历代码,打印输出吧
}

7.排序,map中的sort问题
map中的元素是自动按Key升序排序,所以不能对map用sort函数;
STL中默认是采用小于号来排序的,以上代码在排序上是不存在任何问题的,因为上面的关键字是int 型,它本身支持小于号运算,在一些特殊情况,比如关键字是一个结构体,涉及到排序就会出现问题,因为它没有小于号操作,insert等函数在编译的时候过不去

第一种:小于号重载,程序举例。

#include <iostream>
#include <string>
#include <map>
using namespace std;
typedef struct tagStudentinfo
{
       int niD;
       string strName;
       bool operator < (tagStudentinfo const& _A) const
       {     //这个函数指定排序策略,按niD排序,如果niD相等的话,按strName排序
            if(niD < _A.niD) return true;
            if(niD == _A.niD)
                return strName.compare(_A.strName) < 0;
        return false;
       }
}Studentinfo, *PStudentinfo; //学生信息
int main()
{
    int nSize;   //用学生信息映射分数
    map<Studentinfo,int> mapStudent;
    map<Studentinfo,int>::iterator iter;
    Studentinfo studentinfo;
    studentinfo.niD = 1;
    studentinfo.strName = "student_one";
    mapStudent.insert(pair<Studentinfo, int>(studentinfo, 90));
    studentinfo.niD = 2;
    studentinfo.strName = "student_two";
    mapStudent.insert(pair<Studentinfo, int>(studentinfo, 80));
    for (iter=mapStudent.begin(); iter!=mapStudent.end(); iter++)
        cout<<iter->first.niD<<' '<<iter->first.strName<<' '<<iter->second<<endl;
    return 0;
}

第二种:仿函数的应用,这个时候结构体中没有直接的小于号重载,程序说明

//第二种:仿函数的应用,这个时候结构体中没有直接的小于号重载,程序说明
#include <iostream>
#include <map>
#include <string>
using namespace std;
typedef struct tagStudentinfo
{
       int niD;
       string strName;
}Studentinfo, *PStudentinfo; //学生信息
class sort
{
public:
    bool operator() (Studentinfo const &_A, Studentinfo const &_B) const
    {
        if(_A.niD < _B.niD)
            return true;
        if(_A.niD == _B.niD)
            return _A.strName.compare(_B.strName) < 0;
    return false;
    }
};
int main()
{   //用学生信息映射分数
    map<Studentinfo, int, sort>mapStudent;
    map<Studentinfo, int>::iterator iter;
    Studentinfo studentinfo;
    studentinfo.niD = 1;
    studentinfo.strName = "student_one";
    mapStudent.insert(pair<Studentinfo, int>(studentinfo, 90));
    studentinfo.niD = 2;
    studentinfo.strName = "student_two";
    mapStudent.insert(pair<Studentinfo, int>(studentinfo, 80));
    for (iter=mapStudent.begin(); iter!=mapStudent.end(); iter++)
        cout<<iter->first.niD<<' '<<iter->first.strName<<' '<<iter->second<<endl;
}

3.set容器的用法

1.set容器的常用操作

使用时注意包含头文件<set>    std::set and std::multiset associative containers
s.begin()      返回set容器的第一个元素
s.end()      返回set容器的最后一个元素
s.clear()       删除set容器中的所有的元素
s.empty()     判断set容器是否为空
s.insert()      插入一个元素
s.erase()       删除一个元素
s.size()     返回当前set容器中的元素个数

2.set容器的创建

#include <iostream>
#include <set>
#include <functional>
using namespace std;
set<int> s;
int main(){
   set<int > seta; //默认是小于比较器less<int>的set
   set<int, greater<int> > setb; //创建一个带大于比较器的set,需包含头文件functional
   int a[5] = {1,2,3,4,5};
   set<int > setc(a,a+5); //数组a初始化一个set;
   set<int > setd(setc.begin(),setc.end()); //setc初始化一个set
   //上述两例均为区间初始化
   set<int > sete(setd); //拷贝构造创建set
   return 0;
}

3.set容器的增删改查

①插入

#include <iostream>
#include <set>
using namespace std;
set<int >s;
void setprint(int cnt){
    cout << "Test output :" << cnt << ":" << endl;
    for(set<int>::iterator it = s.begin(); it!= s.end(); it++)
        cout << *it << " ";
    puts("");
    return ;
}
int main(){
    int cnt = 1;
    s.insert(1);
    s.insert(2);
    s.insert(5);
    setprint(cnt++);
    s.insert(2); //set只允许用一个值出现一次,要插入相同元素请用multiset
    setprint(cnt++);
    int a[4] = {11,12,13,14};
    s.insert(a,a+4); //将区间[a, a+4]里的元素插入容器
    setprint(cnt++);
    return 0;
}

②删除

s.erase()       删除一个元素

s.clear()       删除set容器中的所有的元素
#include <iostream>
#include <set>
using namespace std;
set<int >s;
void setprint(int cnt){
    cout << "Test output :" << cnt << ":" << endl;
    for(set<int>::iterator it = s.begin(); it!= s.end(); it++)
        cout << *it << " ";
    puts("");
    return ;
}
int main(){
    int cnt = 1;
    for(int i = 1; i < 11; i++){
        s.insert(i);
    }
    setprint(cnt++);
    s.erase(9); //根据元素删除
    setprint(cnt++);
    set<int>::iterator ita = s.begin();
    set<int>::iterator itb = s.begin();
    s.erase(ita);  //删除迭代器指向位置的元素
    setprint(cnt++);
    ita = s.begin();
    itb = s.begin();
    itb++;itb++;
    s.erase(ita,itb); //删除区间[ita,itb)的元素
    setprint(cnt);
    s.clear();
    return 0;
}

③修改

不能直接修改容器内数据,所以只能删除某元素再插入要修改的数值。

④查找

s.find()        查找一个元素,如果容器中不存在该元素,返回值等于s.end()
#include <iostream>
#include <set>
using namespace std;
set<int >s;
void setprint(int cnt){
    cout << "Test output :" << cnt << ":" << endl;
    for(set<int>::iterator it = s.begin(); it!= s.end(); it++)
        cout << *it << " ";
    puts("");
    return ;
}
int main(){
    int cnt = 1;
    s.insert(1);
    s.insert(2);
    s.insert(5);
    setprint(cnt++);
    if(s.find(2) != s.end()) 
        cout << "2 is existent" << endl;
    else 
        cout << "2 is non-existent" << endl;
    if(s.find(3) == s.end()) 
        cout << "3 is non-existent" << endl;
    else 
        cout << "2 is existent" << endl;
    return 0;
}

4.set的其他常用操作

s.lower_bound() 返回第一个大于或等于给定关键值的元素
s.upper_bound() 返回第一个大于给定关键值的元素
s.equal_range() 返回一对定位器,分别表示 第一个大于或等于给定关键值的元素 和 第一个大于给定关键值
                的元素,这个返回值是一个pair类型,如果这一对定位器中哪个返回失败,就会等于
                s.end()
#include <iostream>
#include <set>
using namespace std;
int main(){
    set<int> s;
    s.insert(1);
    s.insert(2);
    s.insert(5);
    cout << "lower_bound & upper_bound test:" << endl;
    cout << "第一个大于或等于3的元素: " << *s.lower_bound(3) << endl;
    cout << "第一个大于或等于2的元素: " <<*s.lower_bound(2) << endl;
    cout << "第一个大于2的元素: " <<*s.upper_bound(2) << endl;
    cout << "equal_range test:" << endl;
    cout << "第一个大于或等于2的元素: " <<  *s.equal_range(2).first << endl;
    cout << "第一个大于2的元素: " << *s.equal_range(2).second << endl;
    return 0;
}

②判断元素是否在set中 & 判断set是否为空

#include <iostream>
#include <set>
#include <functional>
using namespace std;
int main(){
    set<int > s;
    if(s.empty()) cout << "容器为空" << endl;
    s.insert(1);
    if(!s.empty()) cout << "容器不为空" << endl;
    if(s.count(1)) cout << "1在容器中" << endl;
    if(!s.count(2)) cout << "2不在容器中" << endl;
    return 0;
}

③自定义比较函数

#include <iostream>
#include <set>
#include <functional>
using namespace std;
struct cmp{
    bool operator () (const int &a, const int &b){
        return a > b;
    }
};
set<int, cmp>s; //自定义排序函数构造set
void setprint(int cnt){
    cout << "Test output :" << cnt << ":" << endl;
    for(set<int,cmp>::iterator it = s.begin(); it!= s.end(); it++)
        cout << *it << " ";
    puts("");
    return ;
}
int main(){
    s.insert(1);
    s.insert(2);
    s.insert(6);
    setprint(1);
    return 0;
}

体会:

由于疫情的原因,在家已经持续上了9周的课了。要说在家没有一点点的懈怠,每天都认真地学习,那是不可能的。每天都憋在家里,这么可能一点懈怠都没有。现在已经上了这么多的课了,越来越能感受到C++这门课的难度,越来越觉得自己不是那么聪明。有时候也感觉到自己特别的迷茫,没有一个明确的方向,但路都是自己选的,既然转到了计算机专业,那就努力学习吧。虽然,自己的脑子不是那么聪明,但也可以通过自己的努力来掌握所学习到的知识,勤能补拙嘛。。。
加油,相信自己一定能行!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值