C++STL(标准模板库)学习

STL六大组件

1.容器:指各种数据结构,存放数据
2.算法:各种常用算法
3.迭代器:是容器与算法之间的胶合剂
4.仿函数:行为类似函数
5.适配器
6.空间配置器
算法分为质变算法(会在过程中改变容器中的存放数据)和非质变算法(不改变)
算法通过迭代器访问容器中的元素
迭代器也分种类:输入,输出,前向,双向,随机访问,常用的容器中迭代器都为双向随机访问迭代器,他们两个的功能更为强大

vector

vector存放内置数据类型

	vector<int>v;
	vector<int>::iterator itBegin= v.begin();//起始迭代器,指向的是容器中的第一个元素
	vector<int>::iterator itEnd= v.end(); //结束迭代器,指向的是容器中最后一个元素的下一个位置 
	while(itBegin!=itEnd)
	{
		cout<<*itBegin<<endl;
		itBegin++;	
	}
	//第二种遍历使用for循环,不再列举
	//第三种,使用for_each算法
	for_each(v.begin(),v.end(),print);
	//下面是底层源码实现,还是一个for循环
	for (; __first != __last; ++__first)
	__f(*__first);
	//在这里for_each函数中的第三个参数我传递了一个自定义的函数的函数名
	//这个函数的返回值是void,需要的一个参数是int,正好是我前面定义过的vector中存放的参数类型。
	//可以看到,在源码中,实现逻辑就是在遍历过程中每遍历一个,就调用这个函数一次
	//没有返回值,传入的参数正是容器中存放的数据类型.
	

vector中是采用动态扩展机制,并不是在原空间之后直接插入,而是寻找一片更大的空间将原来的数据拷贝过去

vector中的容量和大小

vector<int> a;
a.capacity()//查看容器的容量
a.size()//查看容器的大小
//容量>=大小

vector中的swap函数

vector<int> v1;
vector<int> v2;
v1.swap(v2);//这个函数的作用就是交换两个容器的内容
//接下来展示实际应用
for(int i=0;i<10000;i++)
{
	v1.push_back(i);
}
v1.resize(3);//收缩v1的大小
cout<<v1.capacity()<<" "<<v1.size();
//输出分别是一万多和3,可以看到,虽然v1的大小被重置了
//但是它的容量并没有得到实质性的改变,这样会造成空间的浪费
vector<int>(v1).swap(v1);
//这时候再查看v1的容量和大小,就会发现他们已经变成了3,3
//这个语句先是用v1创建了一个匿名对象,然后再进行交换
//创建的匿名对象的容量是根据3来分配的,而交换后也不必再担心匿名对象所占用的内存关系
//系统在匿名对象完成功能后,就会自动回收匿名对象所占用的内存空间。

vector中reserve的使用

reserve指为vector分配内存空间,vector在使用的时候,如果不断插入数据,vector就会不断地进行动态扩展,不断地寻找新空间,将原数据拷贝到新空间,再释放掉旧空间。但是如果在插入数据之前就知道要插入多少数据,就可以为vector先reserve出这么大的空间,这样在之后的插入数据的过程中就不再需要动态扩展去分配空间了

vector<int>v1;
v1.reserve(1000);

string

find()和rfind()的区别
find()是从左往右查找,rfind()从右往左查找,但是最后计算下标位置都是从左往右计算

deque(读作:戴克)

deque(双端数组,可以对头端进行插入删除操作)

deque的内部工作原理

deque内部有个中控器,里面存储着每段缓冲区的地址,而真正的数据呢,就储存在这些缓冲区中,所以deque访问数据,要通过中控器中的这些缓冲区的地址去访问
deque中没有容量这一概念,但size还是有的,这也是deque和vector的不同之一

deque 在头部插入和删除

deque<int> d;
d.push_front(20);//在头部插入
d.pop_front(20);//在头部删除

stack

stack中不能有遍历行为,只能访问栈顶元素,要访问第二个元素只有把栈顶元素拿出来

queue(发音:Q)

同样队列中不能有遍历行为,只有队头和队尾能被外界访问

list

list中不支持用下标[ ]或用at( )来访问元素,因为list中不支持随机访问,它的迭代器是双向迭代器,只支持++或–操作

list中的sort

所有不支持随机访问的数据结构都不能使用全局的算法,而是在其内部,有属于自己的算法

list<int> l;
sort(l.begin(),l.end());//报错
l.sort();//可以(默认是升序排列)
//**************降序排列**********
bool myCom(int v1,int v2)//这里数据类型得是容器中包含的数据类型
{
	return v1>v2;//升序直接让前一个数大于后一个
}
list<int> v;
v.sort(myCom);//即可实现降序

set

set容器中会将插入的值自动进行排序,set容器中也不会允许有重复的值,插两个相同的值,最后容器中只会有一个

set改变排序规则

class Com
{
	bool opereator()(int v1,int v2)
	{
		return v1>v2;
	}
};
set<int,Com> s; //这样即可将set内的排序规则变成降序

pair

pair可以包含两个元素
可以用作函数返回值

//创建对组的两种方式
pair<int,bool> p(10,true);
pair<string ,int> p =make_pair("asd",10);

map

map容器的默认排序规则是按照key值从小到大进行排序

//map中插入元素
map<int,int> a;
a.insert(pair<int,int>(1,10));
a.insert(make_pair(2,20));
a[4]=40;//直接插入
//不建议用中括号的形式往map中插入数据,如果map中没有对应的键,它就会自动创建一个

函数对象

重载函数调用操作符的类,其对象称为函数对象

函数对象的基本使用

//1。函数对象在使用时,就可以把它当成
//一个函数那样来使用,有返回值,有参数
class MyAdd
{
	int opereator()(int a,int b)
	{
		return a+b;
	}
};
MyAdd myAdd;
cout<<myAdd(1,2);//输出3
//2.既然这是一个类,那么在类中自然也可以定义其他的数据成员
//3.既然是一个类,那么也可以被当作参数传递进入函数的内部

谓词

谓词:返回bool类型的函数对象称为谓词
如果opreator()接受一个参数,叫一元谓词,接受两个参数,就叫二元谓词

class GreaterFive
{
	bool opereator()(int v)//这就是一个一元谓词
	{
		return v>5;
	}
};
vector<int> a;
find_if(a.begin(),a.end(),GreaterFive());
//find_if按条件查找
//底层源码显示,find_if无非就是遍历区间
//每一次就调用一次谓词,将容器内的数据传入
//然后判断如果谓词的返回值为真,就退出遍历
//返回这个元素的迭代器的位置

对于二元谓词,其实在前面已经介绍过,排序的时候用到的比较两个数的函数其实就是二元谓词

内建函数对象

STL中提供了一套函数对象,可以直接拿来使用

#include<functional>
negate<int> n;//这就是对一个属取反
n(50);
plus<int> a;
a(10,20);
//实现两个数相加,只需提供给一个模板参数
//因为它只支持两个同类型的数相加

算法

transform

class Trans{
	int opereator()(int v)
	{	
		return v;
	}
};
vector<int> v1;
vector<int> v2;
v2.resize(v1.resize());
//这一步操作必须要有,必须先为另一个容器开辟孔空间才能将容器中的值搬运过去
transform(v1.begin(),v1.end(),v2.end(),Trans());
//transform函数是将一个容器中的数据搬到另一个容器中
//需要提供一个仿函数,来告诉transform函数在搬运的过程中应该怎么操作容器中的数据
//所以返回值就不能再是void了,而应该返回容器中的数据类型

find

find算法虽然简单,但要记得,在用find查找自定义的数据的时候,需要告诉编译器应该按何种规则查找,也就是说当哪些条件满足时,这个数据才能算作相等,也就是说需要重载==运算符,
当然,要注意,在重载等号运算符供STL算法使用时,不能忘记加const

class Example
{
	string name;
	int num;
	bool operator==(const Example&e)
	{
		return this->name==e.name&&this->num==e.num;
	}
{;

find_if

这个算法可以叫做条件查找,比如说查找一下一个容器中有没有大于5的元素,就用这个算法

adjacent_find

adjacent_find算法,查找容器中是否有重复相邻元素,如果有,就会返回指向重复相邻元素中的第一个元素的迭代器,如果没找到,就返回指向末尾的迭代器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值