以下是我对STL标准模板库的个人见解
目录
STL标准模板库大致分为
—— 1.容器(Containers):可容纳任意数据类型的数据结构。
—— 2.迭代器(Iterators) :可依次存取容器内的东西。
—— 3.算法(Algorithms):算法作用于容器。
下面正式开始讲解——
迭代器(下面只说常见的迭代器)
正向迭代器:支持++,--,赋值,取地址,==,!=判断等操作。 (作者忘记打上去了)
随机迭代器(支持几乎所有算法,如:++,--,拥有下标等):vector,deque等支持随机迭代器。
双向迭代器(只支持++,--,无下标):list,set,map支持双向迭代器。
不支持迭代器(字面意思):stack,queue,priority_queue不支持迭代器。
定义迭代器:vector<int>::iterator it;
容器名 迭代器 变量名
定义反向迭代器:vector<int>::reverse_iterator it;
迭代器遍历:
#include<bits/stdc++.h>
using namespace std;
int main(){
int a[]={1,2,3,4,5};
vector<int> v(a,a+5);
vector<int>::iterator it;
for(it=v.begin();it<v.end();it++){//注意<要根据容器适配的迭代器来使用
cout<<*it<<' ';
}
return 0;
}
输出:1 2 3 4 5
反向迭代器遍历:
#include<bits/stdc++.h>
using namespace std;
int main(){
int a[]={1,2,3,4,5};
vector<int> v(a,a+5);
vector<int>::reverse_iterator rit;
for(rit=v.rbegin();rit<v.rend();rit++){//注意<要根据容器适配的迭代器来使用
cout<<*rit<<' ';
}
return 0;
}
输出:5 4 3 2 1
vector(向量)
解释:vector是一个能够存放任意元素的动态数组(原数个数可变)。
vector常用函数
排序操作:
#include<bits/stdc++.h>
using namespace std;
int main(){
int a[]={4,3,1,5,2};
vector<int> v(a,a+5);
sort(v.begin(),v.end());
for(int i=0;i<v.size();i++){
cout<<v[i]<<" ";
}
return 0;
}
输出:1 2 3 4 5
逆序操作(建议看这个):
#include<bits/stdc++.h>
using namespace std;
int main(){
int a[]={4,3,1,5,2};
vector<int> v(a,a+5);
for(int i=0;i<v.size();i++){//输出原数组
cout<<v[i]<<" ";
}
cout<<endl;
sort(v.begin(),v.end());//排序
for(int i=0;i<v.size();i++){//输出从小到大排序后的数组
cout<<v[i]<<" ";
}
cout<<endl;
reverse(v.rbegin(),v.rend());//进行逆序
for(int i=0;i<v.size();i++){//输出从小到大排序后又逆序后的数组
cout<<v[i]<<" ";
}
return 0;
}
输出:4 3 1 5 2
1 2 3 4 5
5 4 3 2 1
vector构造方法(1)
#include<bits/stdc++.h>
using namespace std;
int main(){
vector<int> v;
v.push_back(10);
for(int i=0;i<v.size();i++){
cout<<v[i]<<" ";
}
return 0;
}
输出:10
注意:不要在用这种方法的时候,不存入数就使用下标,会报错或者无输出。
vector构造方法(2)
#include<bits/stdc++.h>
using namespace std;
int main(){
vector<int> v(5);
for(int i=0;i<v.size();i++){
cout<<v[i]<<" ";
}
return 0;
}
输出:0 0 0 0 0
vector构造方法(3)
#include<bits/stdc++.h>
using namespace std;
int main(){
vector<int> v(5,10);
for(int i=0;i<v.size();i++){
cout<<v[i]<<" ";
}
return 0;
}
输出:10 10 10 10 10
vector构造方法(4)
#include<bits/stdc++.h>
using namespace std;
int main(){
int a[]={1,2,3,4,5};
vector<int> v(a,a+5);
for(int i=0;i<v.size();i++){
cout<<v[i]<<" ";
}
return 0;
}
输出:1 2 3 4 5
deque(双向队列)
解释:所有适用于deque,但是deque在头尾增删元素较好。
deque存数比vector快
那么我就不多说了,不会的请看——标题:vector(向量)回顾!!!
可是deque有vector没有的两个函数:1. push_front(val)——将val插入容器头部。
2.pop_front()——删除头部元素。
算了给你们看一看之前vector的函数吧(作者原封不动的从前面搬过来的,其中得你们总结改一改呦!!!)蛤蛤蛤!!!
演示如下:
#include<bits/stdc++.h>
using namespace std;
int main(){
int a[]={2,3,4,1};
deque<int> d(a,a+4);
printf("原数组长度:%d\n",d.size());
d.push_front(5);
printf("头部增加后长度:%d\n\n",d.size());
printf("排序前:\n");
for(int i=0;i<d.size();i++){
cout<<d[i]<<' ';
}
sort(d.begin(),d.end());
printf("\n排序后:\n");
for(int i=0;i<d.size();i++){
cout<<d[i]<<' ';
}
cout<<endl;
d.pop_front();
printf("头部减少后长度:%d\n",d.size());
for(int i=0;i<d.size();i++){
cout<<d[i]<<' ';
}
return 0;
}
输出:原数组长度:4
头部增加后长度:5 排序前:
5 2 3 4 1
排序后:
1 2 3 4 5
头部减少后长度:4
2 3 4 5
list(链表)
解释:链表可以是一个线性单向链表结构 或者 线性双向链表结构。
首先我们来重温顺序存储的优缺点吧!
优点:
- 1.无需为表示节点间的逻辑关系而增加额外的存储空间;
- 2.可方便地随机存取表中任意一个元素。
缺点:
- 1.插入或删除平均要移动一半的节点(所需时间太长);
- 2.顺序表占用连续的存储空间过多。
接下来就是讲新知识——list(链表)!
链表:
优点:
- 1.插入或删除简单方便。
- 2.无需增加的额外存储空间。、
缺点:
- 1.没有下标(占用内存不一定连续)。
- 2.检索性能不太好(找数据需要一个一个找)。
list常用函数
演示小代码:
#include<bits/stdc++.h>
using namespace std;
void print(list<int> l){
list<int>::iterator it;//list只支持双向迭代器
for(it=l.begin();it!=l.end();it++){//因为list只支持双向迭代器,所以不能用<号等比较符号,只能用!=或==
cout<<*it<<' ';
}
cout<<endl;
}
int main(){
int x,y;
int a[]={10,20,30,40,50,60};
list<int> l(a,a+6);
cout<<"当前数组是:";
print(l);
cout<<endl;
list<int>::iterator it=l.begin();//list只支持双向迭代器
cout<<"请输入想要插入的数据(整数类型)x和插入位置y:";
cin>>x>>y;
for(int i=1;i<y;i++){//list没有下标,需要用迭代器遍历
it++;
}
l.insert(it,x);
cout<<"插入后的数组:";
print(l);
return 0;
}
输入:0 0
输出:
当前数组是:10 20 30 40 50 60
请输入想要插入的数据(整数类型)x和插入位置y:0 0
插入后的数组:0 10 20 30 40 50 60
set(集合)
解释:set是一个关联容器,是排好的集合,set中不能有重复的元素。
特点:不能直接修改,应该先删除该元素,再插入新元素。
扩展:
- 在排序中,会有比较器,默认比较器是less<数据类型>(从小到大排序)。
- greater<数据类型>(从大到小排序)
用sort来排序,如:set<int,less<数据类型> >(记住在两个>之间要加一个空格' ')
正序:
#include<bits/stdc++.h>
using namespace std;
int main(){
int a[]={40,20,60,10,50,30};
set<int> s(a,a+6);//默认less<数据类型>(从小到大)
set<int>::iterator it;
cout<<"从小到大排序:";
for(it=s.begin();it!=s.end();it++){
cout<<*it<<' ';
}
return 0;
}
输出:
从小到大排序:10 20 30 40 50 60
逆序:
#include<bits/stdc++.h>
using namespace std;
int main(){
int a[]={40,20,60,10,50,30};
set<int,greater<int> > s(a,a+6);
set<int>::iterator it;
cout<<"从大到小排序:";
for(it=s.begin();it!=s.end();it++){
cout<<*it<<' ';
}
return 0;
}
输出:
从大到小排序:60 50 40 30 20 10
map(映射)
解释:关联容器,map的每一个元素部分都分为关键字与值两部分,容器中的元素是按关键字排序的,并且不允许有多个元素的关键字相同(也就是每一个关键字只能在map里),同时不能直接改变map中的关键字。
map的定义:map<关键字,数值>
通俗解释:map的同父异母兄弟:pair(一对)
学术解释:map这个概念在STL中有专门的数据结构——pair。
pair有一个相关函数make_pair()(将数值传到pair中)和两个成员名first(关键字)和second(数值)。
pair:pair是将两个数据组合成一个数据。pair是结构体。
演示小代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
map<int,string> m;
m[1000]="zhang";//注意
m[1002]="zhao";
m[1003]="sun";
m[1001]="wang";
m[1000]="li";//注意
cout<<m[1000]<<endl;//因为map不许有重复的关键字,所以"li"把"zhang"给替代了
pair<int,string> p(1004,"zhou");
pair<int,string> p2(1004,"wu");
m.insert(p);
m.insert(p2);
map<int,string>::iterator it;
it=m.find(1003);
cout<<"删除前:"<<endl;
if(m.count(1003)){
cout<<"1003 找到了,名字为:"<<it->second<<endl;
}else{
cout<<"1003 找不到!"<<endl;
}
m.erase(1003);
cout<<"删除后:"<<endl;
if(m.count(1003)){
cout<<"1003 找到了,名字为:"<<it->second<<endl;
}else{
cout<<"1003 找不到!"<<endl;
}
for(it=m.begin();it!=m.end();it++){
cout<<it->first<<" "<<it->second<<endl;
}
return 0;
}
输出:
li
删除前:
1003 找到了,名字为:sun
删除后:
1003 找不到!
1000 li
1001 wang
1002 zhao
1004 zhou
作者最后的话(求了看看吧!)
这下子我们一口气将STL中常用的一大部分讲完了,请先缓一缓,自己去写写代码,多多记忆,这样才能将收益最大化。等下一篇,我们将剩余的stack,queue,priority_queue也一次性讲完!(最后补充一点——千万要记住在两个>之间加一个空格' '呀!)
最后,本篇文章是作者自己学习过后自行总结而成,可能会有些缺漏,我就在此,请看官们赐教!
最后的最后:
制作不易,点个赞吧!!!
制作不易,点个赞吧!!!
制作不易,点个赞吧!!!