vector(动态数组)

尾部添加,push_back()

#include <iostream>
#include <vector>
using namespace std;int main(int argc, char *argv[]) {vector<int> v;int n;cout<<"输入最大值n:"<<endl;cin>>n;for(int i=0;i<n;i++) {v.push_back(i);}
}

中间插入(前插入&后插入),insert()

int main(int argc, char *argv[]) {vector<int> v{3,2,6,5,0};//insert begin+n是在从前往后数,第n个元素之后插入v.insert(v.begin()+2,111);//3 2 111 6 5 0print_container1(v);//insert end + n 是在从后往前数,第n个元素之前插入v.insert(v.end()-1,111);//3 2 6 5 111 0print_container1(v);
}

中间删除,erase()

v.erase(v.begin());//删除第一个数(下标为0)
v.erase(v.end());//删除最后一个数(下标为n-1)
v.erase(v.begin()+x,v.end()-y);//删除下标0+x~n-1-y的数/*
思考:
vector<int> v = {0,1,2,3,4,5,6,7,8,9};
v.erase(v.begin()+2,v.end()-3);结果:0 1 7 8 9
只保留了前2个数和后3个数。因此,v.erase(v.begin()+x,v.end()-y)的作用就是保留前x个数和后y个数的意思
*/

erase实例:去除偶数

vector<int> k{0,1,2,3,4,5,6,7,8,9};
vector<int> tmp = k;//不破坏原数组
for(vector<int>::iterator it = tmp.begin();it!=tmp.end();){if(*it%2==0){//*it是当前下标的数,it是指向当前位置数的迭代器(指针)it = tmp.erase(it);//把当前位置的迭代器(指针)删除,就删除这个指针所指向的数,因此这个数就被删除了}else{it++;}
}
print_container1(v);
/*结果:
1 3 5 7 9
*/

数组长度&内存申请长度,size()&capacity()

//假设我往数组v中推了10个数k.size();//10
k.capacity();//16//假设我往数组v中推了33个数k.size();//33
k.capacity();//64//假设我往数组v中推了1025个数k.size();//1025
k.capacity();//2048/*
因此,不难得出结论,size()是数组真实的长度,capacity()是数组占用内存的长度
*/

转置,reverse()

vector<int> v = {0,1,2,3,4,5,6,7,8,9};
reverse(v.begin()+2, v.end()-2);
for (int i=0 ;i<v.size(); i++) {cout<<v[i]<<endl;
}
/*
结果:0 1 7 6 5 4 3 2 8 9
倒置的输入参数与insert同理,倒置的作用就是把范围内的数组颠倒了
*/

排序,sort()

//自定义比较函数
bool Comp(const int &a,const int &b){return a>b;
}
int main(int argc, char *argv[]) {vector<int> v = {2,1,3,5,7,9,8,0,6,4};sort(v.begin(), v.end());//默认升序:0 1 2 3 4 5 6 7 8 9sort(v.begin(), v.end(),Comp);//降序:9 8 7 6 5 4 3 2 1 0
}

字符串的输入

#include <iostream>using namespace std;
int main(int argc, char *argv[]) {string s1;string s2;char s[100];scanf("%s",s);//scanf输入速度比cin快得多,但是scanf是C函数,不可以输入strings1 = s;//因此需要用等号赋值给string(但是这个操作不好,用printf会报错,后面会说的)cout<<s1<<endl;cin>>s2;//但是用cin就方便很多cout<<s2<<endl;}

string实例,求一个整数各位数的和

经常会遇到这样一种情况,有一个数字,需要把每一位给提取出来,如果用取余数的方法,花费的时间就会很长,所以可以当成字符串来处理,方便、省时。

#include<iostream>
#include<string>using namespace std;
int main(int argc, char *argv[]) {string s;s = "123456789";int sum = 0;for(int i = 0; i < s.size(); ++i){switch(s[i]){case '1': sum += 1;break;case '2': sum += 2;break;case '3': sum += 3;break;case '4': sum += 4;break;case '5': sum += 5;break;case '6': sum += 6;break;case '7': sum += 7;break;case '8': sum += 8;break;case '9': sum += 9;break;default:break;}}cout << sum << endl;return 0;
}/*输出结果:
45
*/

C语言的一些遗留问题,比如使用string类的自身方法c_str()去处理string和char*赋值问题,(这就是c++做得还不够好的地方)

#include<iostream>
#include<string>
#include<cstdio>//需要包含cstring的字符串的库
using namespace std;int main(){string s_string;char s_char[1000];scanf("%s",s_char);s_string = s_char;printf("s_string.c_str():%s\n", s_string.c_str());//printf输出char*时用c_str处理,c_str()函数返回一个指向正规C字符串的指针, 内容与本string串相同cout<<"s_string:"<<s_string<<endl;printf("s_char:%s\n",s_char);cout<<"s_char:"<<s_char<<endl;cout<<"s_string"<<s_string<<endl;}

查找,find()

以及⬇️

反向查找,rfind()

首次出现位置,find_first_of()

最后出现位置,find_last_of()

这些我就不细说了,用法都是一样的,都是返回一个下标

#include<cstring>
#include<cstdio>
#include<iostream>
using namespace std;int main(int argc, char *argv[]) {find函数返回类型 size_typestring s = "1a2b3c4d5e6f7jkg8h9i1a2b3c4d5e6f7g8ha9i";string flag;string::size_type position;//find函数返回“jk”在s中的下标位置position = s.find("jk");cout<<position<<endl;if (position != s.npos){ //如果没找到,返回一个特别的标志c++中用npos表示,我这里npos取值是4294967295printf("position is : %lu\n" ,position);}else{printf("Not found the flag\n");}
}
/*
输出结果:
13
position:13
*/

关于string::size_type 的理解:

在C++标准库类型 string ,在调用size函数求解string 对象时,返回值为size_type类型,一种类似于unsigned类型的int 数据。可以理解为一个与unsigned含义相同,且能足够大能存储任意string的类型。在C++ primer 中 提到 库类型一般定义了一些配套类型,通过配套类型,库类型就能与机器无关。我理解为 机器可以分为16位 32位64位等,如果利用int等内置类型,容易影响最后的结果,过大的数据可能丢失。

string::size_type 的理解_nibiebiwo的博客-CSDN博客

查找子串

position=s.find("b",5);//查找从某个位置之后第一次出现子串的位置

查找所有子串出现的位置

//查找s 中flag 出现的所有位置。
string s("1a2b3c4d5e6f7jkg8h9i1a2b3c4d5e6f7g8ha9i");
flag="a";
position=0;
int i=1;
while((position=s.find(flag,position))!=string::npos){cout<<"position"<<i<<":"<<position<<endl;position++;i++;
}

求和,accumulate()

#include <numeric>
//起始位置,结束位置,起始累加值(一般都是从0开始吧)
accumulate(v.begin(),v.end(),0);

vector数组的3种遍历方法,我写了三个都挺好用的,可以适当修改一下输出格式

void print_container1(vector<int> vec){for(vector<int>::iterator it = vec.begin();it!=vec.end();it++){cout<<*it<<endl;}
}
void print_container2(vector<int> vec){vector<int>::iterator it = vec.begin();while(it!=vec.end()) {cout<<*it<<endl;it++;}
}
void print_container3(vector<int> vec){for(int i=0;i<vec.size();i++){cout<<vec[i]<<endl;}
}

set容器

set是用红黑树的平衡二叉索引树的数据结构来实现的,插入时,它会自动调节二叉树排列,把元素放到适合的位置,确保每个子树根节点的键值大于左子树所有的值、小于右子树所有的值,插入重复数据时会忽略。set迭代器采用中序遍历,检索效率高于vector、deque、list,并且会将元素按照升序的序列遍历。set容器中的数值,一经更改,set会根据新值旋转二叉树,以保证平衡,构建set就是为了快速检索。

multiset,与set不同之处就是它允许有重复的键值。

#include<iostream>
#include<set>
using namespace std;int main(int argc, char *argv[]) {set<int> v;v.insert(1);//边插边排序v.insert(3);v.insert(5);v.insert(2);v.insert(4);v.insert(3);//会被忽略//中序遍历 升序遍历for(set<int>::iterator it = v.begin(); it != v.end(); ++it){cout<<*it<<" ";}for(set<int>::reverse_iterator rit = v.rbegin(); rit != v.rend(); ++rit){cout<<*rit<<" ";}
}
/*结果:
1 2 3 4 5 //升序iterator
5 4 3 2 1 //降序reverse_iterator
*/

自定义比较函数,insert的时候,set会使用默认的比较函数(升序),很多情况下需要自己编写比较函数。

1、如果元素不是结构体,可以编写比较函数,下面这个例子是用降序排列的(和上例插入数据相同):

#include<iostream>
#include<set>
using namespace std;struct Comp{//重载()bool operator()(const int &a, const int &b){return a > b;}
};
int main(int argc, char *argv[]) {set<int> v;v.insert(1);v.insert(3);v.insert(5);v.insert(2);v.insert(4);v.insert(3);for(set<int,Comp>::iterator it = v.begin(); it != v.end(); ++it){cout << *it << " ";}cout << endl;for(set<int,Comp>::reverse_iterator rit = v.rbegin(); rit != v.rend(); ++rit){cout << *rit << " ";}cout << endl;
}
/*结果://这个之前的正好相反
5 4 3 2 1
1 2 3 4 5
*/

2、元素本身就是结构体,直接把比较函数写在结构体内部,下面的例子依然降序:

#include<iostream>
#include<set>
#include<string>
using namespace std;struct Info{string name;double score;//重载 <bool operator < (const Info &a) const{return a.score < score;}
};
int main(int argc, char *argv[]) {set<Info> s;Info info;info.name = "abc";info.score = 123.3;s.insert(info);info.name = "EDF";info.score = -23.53;s.insert(info);info.name = "xyz";info.score = 73.3;s.insert(info);for(set<Info>::iterator it = s.begin(); it != s.end(); ++it){cout<<(*it).name<<":"<<(*it).score<<endl;}cout << endl;for(set<Info>::reverse_iterator rit = s.rbegin(); rit != s.rend(); ++rit){cout<<(*rit).name<<":"<<(*rit).score<<endl;}cout << endl;
}
/*
abc:123.3
xyz:73.3
EDF:-23.53EDF:-23.53
xyz:73.3
abc:123.3
*/

multiset与set的不同之处就是key可以重复,以及erase(key)的时候会删除multiset里面所有的key并且返回删除的个数。

map容器

map也是使用红黑树,他是一个键值对(key:value映射),遍历时依然默认按照key程序的方式遍历,同set。

#include<iostream>
#include<map>
#include<string>using namespace std;int main(int argc, char *argv[]){map<string,double> m;//声明即插入m["li"] = 123.4;m["wang"] = 23.1;m["zhang"] = -21.9;m["abc"] = 12.1;for(map<string,double>::iterator it = m.begin(); it != m.end(); ++it){//first --> key second --> valuecout << (*it).first << ":" << (*it).second << endl;}cout << endl;
}
/*结果:
abc:12.1
li:123.4
wang:23.1
zhang:-21.9
*/

multimap

multimap由于允许有重复的元素,所以元素插入、删除、查找都与map不同。

插入insert(pair<a,b>(value1,value2)),至于删除和查找,erase(key)会删除掉所有key的map,查找find(key)返回第一个key的迭代器

#include <iostream>
#include <map>
#include <string>
using namespace std;int main(int argc, char *argv[]) {multimap<string,double> m;m.insert(pair<string,double>("Abc",123.2));m.insert(pair<string,double>("Abc",123.2));m.insert(pair<string,double>("xyz",-43.2));m.insert(pair<string,double>("dew",43.2));for(multimap<string,double>::iterator it = m.begin(); it != m.end(); ++it ){cout << (*it).first << ":" << (*it).second << endl;}cout << endl;}
/*结果:
Abc:123.2
Abc:123.2
dew:43.2
xyz:-43.2
*/

deque

deque和vector一样,采用线性表,与vector唯一不同的是,deque采用的分块的线性存储结构,每块大小一般为512字节,称为一个deque块,所有的deque块使用一个Map块进行管理,每个map数据项记录各个deque块的首地址,这样以来,deque块在头部和尾部都可已插入和删除元素,而不需要移动其它元素。

使用push_back()方法在尾部插入元素,

使用push_front()方法在首部插入元素,

使用insert()方法在中间插入元素。

一般来说,当考虑容器元素的内存分配策略和操作的性能时,deque相对vectore更有优势。

(下面这个图,我感觉Map块就是一个list< map<deque名字,deque地址> >)


deque的一些操作

#include <iostream>
#include <deque>
using namespace std;int main(int argc, char *argv[]) {deque<int> d;//尾部插入d.push_back(1);d.push_back(3);d.push_back(2);//头部插入d.push_front(10);d.push_front(-23);//中间插入d.insert(d.begin() + 2,9999);//清空d.clear();//从头部删除元素d.pop_front();//从尾部删除元素d.pop_back();//中间删除d.erase(d.begin()+2,d.end()-5);//正方向遍历for(deque<int>::iterator it = d.begin(); it != d.end(); ++it ){cout << (*it) << " ";}cout << endl << endl;//反方向遍历for(deque<int>::reverse_iterator rit = d.rbegin(); rit != d.rend(); ++rit ){cout << (*rit) << " ";}cout << endl << endl;
}

list(双向链表)

双向链表,常见的一种线性表,简单讲一下吧

插入:push_back尾部,push_front头部,insert方法前往迭代器位置处插入元素,链表自动扩张,迭代器只能使用+±-操作,不能用+n -n,因为元素不是物理相连的。

遍历:iterator和reverse_iterator正反遍历

删除:pop_front删除链表首元素;pop_back()删除链表尾部元素;erase(迭代器)删除迭代器位置的元素,注意只能使用+±-到达想删除的位置;remove(key) 删除链表中所有key的元素,clear()清空链表。

查找:it = find(l.begin(),l.end(),key)

排序:l.sort()

删除连续重复元素:l.unique() 【2 8 1 1 1 5 1】 --> 【 2 8 1 5 1】

bitset
 
很少用到的容器,随便过一下

stack(栈)

#include <iostream>
#include <stack>
using namespace std;int main(int argc, char *argv[]){stack<int> s;s.push(1);s.push(2);s.push(4);s.push(5);cout<<"s.size():"<<s.size()<<endl;while(!s.empty()){cout<<s.top()<<endl;s.pop();}
}
/*结果:
s.size():4
5
4
2
1
*/

queue(队列)

queue有入队push(插入)、出队pop(删除)、读取队首元素front、读取队尾元素back、empty,size这几种方法,不多说了

priority_queue(优先队列)

#include <iostream>
#include <queue>
using namespace std;int main(int argc, char *argv[]) {priority_queue<int> pq;pq.push(1);pq.push(3);pq.push(2);pq.push(8);pq.push(9);pq.push(0);cout<<"pq.size:"<<pq.size()<<endl;while(pq.empty() != true){cout << pq.top() << endl;pq.pop();}
}
/*结果:
pq.size:6
9
8
3
2
1
0
*/

重载操作符同set重载操作符

C++的STL库常见函数相关推荐

  1. c++ stl库的基础学习

    stl库学习 学了之后发现,太棒了,终于可以像python一样,不用那么麻烦了 这里面的东西其实都是可以类比到python那里面的 比如vector就是list,map就是dict,set就是会知道排 ...

  2. C++11 中STL库中新增内容

    C++ 11一个比较显著的变化是以前boost库中的一些函数被正式标准化合入到STL中了,本文就简单的介绍一下. 引用包装器(Reference Wrapper) 当模板函数参数为泛型类型的时候,无法 ...

  3. STL库容器vector at函数

    STL库容器vector at函数 v.at(n)返回v指定位置n的元素.at函数比[]运算符更加安全, 因为它不会让你去访问到越界的元素,一旦越界将会在运行时中止程序并抛出一个异常std::out_ ...

  4. c++中algorithm头文件、STL库简介及使用说明

    c++中algorithm头文件.STL库简介及使用说明 c++中algorithm头文件是STL的算法部分,里边定义了各种算法,比如sort之类的.加上algorithm就可以使用stl库里的各种算 ...

  5. STL库中string类内存布局的探究

    在STL中有着一个类就是string类,他的内存布局和存储机制究竟是怎么样的呢? 这就是建立好的string 可以看出,图中用黄色框框标注的部分就是主要区域 我们用来给string对象进行初始化的字符 ...

  6. [c++]巧用stl库-啤酒与尿布

    [c++]<-巧用stl库-> 啤酒与尿布 前言 大家好,楼主计算机专业大学狗一枚.<啤酒与尿布>是专业课的一道课后习题,觉得我个人思路比较新颖,在此分享.能力一般,水平有限, ...

  7. 例题5-3安迪的第一个字典 UVa10815--C++STL库映射set的应用

    前言 不定期更新C++的STL库以及算法练习的笔记 分享给大家 也是督促自己不断努力学习算法与程序设计 学习算法之前,要想高效简洁的写好代码,还需要熟练掌握STL库的一些方法和数据结构 参考书籍: & ...

  8. STL库:string

    STL库:string 文章目录 STL库:string 1.STL库对于string类的介绍 2.string常用接口的掌握 2.1 string的构造接口 2.2 string的容量操作接口 2. ...

  9. STL库:vector

    STL库:vector 文章目录 STL库:vector 1.STL库对vector的官方介绍 2.vecotr的常用接口 2.1 vector的构造函数 2.2 vector的迭代器与遍历操作 2. ...

最新文章

  1. ABP入门系列(7)——分页实现
  2. 浏览器ERR_PROXY_CONNECTION_FAILED解决方法
  3. django项目学习之QQ登录
  4. UVa 103 - Stacking Boxes(dp求解)
  5. java流式传输对象_Java性能:面向教学与流式传输
  6. Page 和Ability之间区别
  7. cent mysql 配置,centos下MySQL安装配置
  8. 【定位问题】基于matlab GUI RSSI无线定位【含Matlab源码 1054期】
  9. python计算两点间距离_已知经纬度坐标求两点间距离,用python表示
  10. 使用python移动复制文件
  11. 迭代法动态生成谢尔宾斯基三角形
  12. 主动学习、纯半监督学习、直推学习的联系与区别
  13. 计算机组装专周实训心得,电脑组装实训心得3篇
  14. linux自动任务计划任务,「linux下的计划任务——只执行一次的定时任务」- 海风纷飞Blog...
  15. 基建不再是架桥铺路,“新基建”正星火驰援行业的数字化转型
  16. 解决谷歌浏览器提示您的链接不是私密链接
  17. 数据结构之链表 - 动图演示
  18. 基于希克斯需求价格弹性计算_#炳哥经济学临考密押DAY1#微观计算题考点大盘点(上)...
  19. Developing a new LMS function
  20. CSLA公链构建多元生态—csla超级公链是什么东西

热门文章

  1. 阿里云国际版查看云服务器ecs实例系统日志和截图-Unirech
  2. 电子设计教程29:滞回比较器(施密特触发器)
  3. consul报错:consul at least one health check on one instance is failing
  4. 谷歌、百度循环多次翻译、语音下载python脚本
  5. n 以内与 n 互素的元素集合必然形成一个循环群
  6. php生成6位id,6位极品微信号?微信号id名字大全
  7. 关于图计算图学习的基础知识概览:前置知识点学习(PGL)[系列一]
  8. 双非跨考(管理跨考计算机)在努力为了研三可以去大厂工作
  9. abap后台作业清理
  10. 响应时间与滤波器截止频率的关系