STL标准模板库(一)

以下是我对STL标准模板库个人见解

目录

STL标准模板库大致分为

迭代器(下面只说常见的迭代器)

vector(向量)

deque(双向队列)

list(链表)

set(集合)

map(映射)

作者最后的话(求了看看吧!)


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中不能有重复的元素。

特点:不能直接修改,应该先删除该元素,再插入新元素。

扩展:

  1. 在排序中,会有比较器,默认比较器是less<数据类型>(从小到大排序)。
  2. 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也一次性讲完!(最后补充一点——千万要记住在两个>之间加一个空格' '呀!)

最后,本篇文章是作者自己学习过后自行总结而成,可能会有些缺漏,我就在此,请看官们赐教!

最后的最后:

!!!

!!!

!!!

  • 37
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值