C++STL常用用法详细总结(待补充)

一、STL概述

C++的标准模板库STL 的一个重要特点是数据结构和算法的分离。STL 中包含的是堆栈、队列和其他许多标准数据结构的实现和许多重要泛化算法的实现。例如,STL中的 sort()函数是完全通用的,可以用它来操作几乎任何数据集合,包括链表、容器和数组。
STL 另一个重要特性是它不是面向对象的。正如名称所暗示的,STL中的类都是模板类。为了具有足够通用性,STL主要依赖于模板而不是封装、继承和多态(面向对象程序设计的3个要素)。在STL中找不到任何明显的类继承关系, 这正是使得STL的组件具有广泛通用性的底层特征。
另外,由于STL 是基于模板、内联函数的使用,追求的是运行的效率,避免了虚函数的开销,这使得生成的代码短小高效。
STL 提供了大量的模板类和函数 ,可以在面向对象程序设计和常规编程中使用。最有用的泛型组件就是迭代器、容器和算法。STL 提供的 70 多个算法都是完全通用的,而且不依赖于任何特定的数据类型。
为了避免和其他头文件冲突, 确保可移植性, 在包含头文件时缺省.h 后缀。

STL中六大组件:
1.容器(Container),是一种数据结构,如list,vector 和deques,以模板类的方法提供。为了访问容器中的数据,可以使用由容器类输出的迭代器。
2. 迭代器(Iterator),提供了访问容器中对象的方法。例如,可以使用一对迭代器指定list或vector中的一定范围的对象。迭代器就如同一个指针。
3. 算法(Algorithm),是用来操作容器中的数据的模板函数。例如,STL用sort()来对一个vector中的数据进行排序,用find()来搜索一个list中的对象,函数本身与他们操作的数据的结构和类型无关,因此他们可以在从简单数组到高度复杂容器的任何数据结构上使用。
4. 仿函数(Functor)
5. 适配器(Adaptor)
6. 分配器(allocator)

二、STL 容器

1.介绍

STL 容器 对最常用的数据结构提供了支持,这些模板的参数允许指定容器中元素的数据类型。因此容器类作为通用元素收集器,就是容纳、包含一组元素或元素集合的对象。C++中的容器类还可以包含混合类型的元素,当容器类包含不同类型的元素时,称为异类容器类 ( heterogeneouscontainer) ;包含相同类型的元素时,称为同类容器类 ( homogenous container )。
容器类库中包括 7 种基本容器:向量 vector、列表 list、双端队列 deque、集合 set、映射 map、栈 stack 和 队列 queue
其中 vector、list、deque 为顺序容器set 和 map 为关系式容器stack 和 queue 为容器适配器(即可以看作由其他容器实现的容器)
在这里插入图片描述

2.vector

vector 容器与数组相比其优点在于它能够根据需要随时自动调整自身的大小以便容下所要放入的元素,vector是一个能够存放任意类型的动态数组。

2.1 vector 的初始化

有以下几种方式:

  1. vector < int > v; //默认初始化,v为空
  2. vector < int > v(10); //定义了10个整型元素的向量(尖括号中为元素类型名,它可以是任何合法的数据类型),但没有给出初值,其值是不确定的
  3. vector < int > v(10,1); //定义了10个整型元素的向量,且给出每个元素的初值为1
  4. vector < int > v(a); //使用a初始化v
  5. vector < int > v(b.begin(),b.end()); //复制 [begin,end) 区间内b数组的元素到v中
2.2 vector 的常用操作
  1. 插入
    (1)v.push_back(x); //在v的尾部插入一个元素x
    (2)v.insert(v.begin(), x); //将x插入到向量v的起始位置前
    (3)v.insert(v.begin(), 3, x) ; //将x分别插入到向量元素位置的0-2处(共3个元素)
    (4)v.insert(v.begin(),b+3,b+6); //将b的第3个元素(从第0个算起)到第5个元素(不包括b+6)全部插入到v.begin()前
  2. 删除
    (1)v.pop_back(); //删除v向量的最后一个元素
    (2)v.erase(v.begin()); //将起始位置的元素删除
    (3)v.erase(v.begin()+1,v.begin()+3); //删除v中第1个(从第0个算起)到第2个元素
    (4)v.clear(); //清空v中的所有元素
  3. v.front(); //返回v的第一个元素
  4. v.back(); //返回v的最后一个元素
  5. v.empty(); //判断v是否为空,空返回ture,不空返回false
  6. v.size(); //返回v中元素个数
  7. v.capacity(); //返回v在内存中总共可以容纳的元素个数
  8. v.resize(10,2); //将v的现有元素个数调至10个,多则删,少则补,其值为2。resize() 改变size() 和capacity() 的返回值。
  9. v.reserve(100); //将v的容量(capacity)扩充至100,这种操作只有在需要给a添加大量数据的时候才显得有意义,因为这将避免内存多次容量扩充操作。 reserve() 不改变size() 返回的值,只改变capacity() 返回的值。
  10. a == b; //a向量与b向量比较,相等则返回1,向量的比较操作还有 !=, >=, <=, >, <
  11. a.swap(b); //将a向量中的元素和b向量中的元素进行整体性交换
2.3 vector 几种常用算法
  1. sort(v.begin(),v.end()); //对v中的从v.begin()(包括)到v.end()(不包括)的元素进行从小到大排列
  2. reverse(v.begin(),v.end()); //对v中的从v.begin()(包括)到v.end()(不包括)的元素倒置,但不排列,如v中元素为1,3,2,4,倒置后为4,2,3,1
  3. copy(v.begin(),v.end(),a.begin()+1); //把v中的从v.begin()(包括)到v.end()(不包括)的元素复制到a中,从a.begin()+1的位置(包括)开始,覆盖掉原有元素
  4. find(v.begin(),v.end(),10); //在v中的从v.begin()(包括)到.end()(不包括v)的元素中查找10,若存在返回其在向量中的位置
2.4 vector 使用举例
  1. 在容器尾部插入和删除元素
vector<int> v;
for(int i=0;i<10;i++)//在最后插入
{
	v.push_back(i);
}
for(int i=0;i<5;i++)//删除最后的元素
{
    v.pop_back();
}

向量元素的索引编号从0 开始,这和数组相同。可通过符号 “[]“来读取和更改这些元素, 但是,将”[]” 应用到向量时,只能用 v[i] 更改一个已经赋值的元素,不能使用 v[i] 来初始化编号为 i 的元素。

即 插入元素不能写成下面这样:
for(int i=0;i<10;i++)
v[i]=i;

  1. 读取容器中的元素
vector<int> v;
//法一:利用数组下标读取
for(int i=0;i<10;i++)
{
    cout<<v[i]<<" ";
}
//法二:利用迭代器读取
vector<int>::iterator it;//声明一个迭代器
for(it=obj.begin();it!=obj.end();it++)
{
	cout<<*it<<" ";
}
  1. 排序
vector<int> v;
v.push_back(1);
v.push_back(3);
v.push_back(0);
sort(v.begin(),v.end());//从小到大排序
reverse(v.begin(),v.end());//将v中元素倒置,变为从大到小 

sort()函数默认是从小到大排序,可重写sort()函数实现从大到小排序。

bool cmp(int a,int b) 
{ 
    return a > b;
} 
int a[20]={2,4,1,23,5,76,0,43,24,65}; 
for(int i=0;i<20;i++) 
    cout<< a[i]<< endl; 
sort(a,a+20,cmp);

3.deque

deque是一种优化了的对序列两端元素进行添加和删除操作的基本序列容器。

3.1 deque 的初始化
  1. deque < int > d; //默认初始化,d为空
  2. deque < int > d(10); //定义了10个整型元素的双端队列(尖括号中为元素类型名,它可以是任何合法的数据类型),但没有给出初值,其值是不确定的
  3. deque < int > d(10,1); //定义了10个整型元素的双端队列,且给出每个元素的初值为1
  4. deque < int > d(a); //复制双端队列a到d
  5. deque < int > d(b.begin(),b.end()); //复制 [begin,end) 区间内b的元素到d中
3.2 deque 的常用操作

deque的各项操作只有以下两点和vector不同:
(1)deque不提供容量操作:capacity() 和 reverse()。
(2)deque直接提供函数完成首尾元素的插入和删除,
d.push_back(x); /在容器尾部添加一个数据
d.push_front(x); //在容器头部插入一个数据
d.pop_back(); //删除容器最后一个数据
d.pop_front(); //删除容器第一个数据
其他均与vector相同。
在这里插入图片描述

4.map

5.set

三、STL 迭代器

1.介绍

在以前的学习中,可以利用指针来访问链表,利用下标来访问数组元素,但在STL 中,容器是封装起来的类模板,其内部结构无从知晓,只能通过容器接口来使用容器,而算法要适用于多种容器,而每个容器存放的元素又可以是任何类型,指针需要知道其指向的元素类型,使用下标需要在相应的容器中重载过下标操作符,显然在容器中需要一种更为抽象的“指针”,这就是迭代器。迭代器本质上不是指针,但不妨把它当作一个指针来使用。STL 的每一个容器类模板中都定义了一组对应的迭代器类。使用迭代器,算法函数可以访问容器中指定位置的元素,而无需关心元素的具体类型。

2.操作

迭代器可以使用以下重载的操作符来操纵迭代器,这些操作符将应用于迭代器对象。
( 1 ) 前置加和后置加操作符"++",用于将迭代器指向下一个数据项。
( 2 ) 前置减和后置减操作符"–",用于将迭代器指向上一个数据项。
( 3 ) 等于操作符"=="和不等于操作符 “! =”,用于测试两个迭代器是否指向同一个位置。
( 4 ) 一个间接访问运算符"*",如果后面的变量 p 是一个迭代器,那么使用*p 就能访问位于p 处的数据。
注意,所有迭代器都拥有上述操作符。但是,vector 模板类是一个特殊的容器,它的迭代器除了拥有这些操作符之外,还有其他操作符。

容器的begin()和end():

3.常用迭代器类型

在这里插入图片描述
(1)随机访问:提供了对数组元素进行快速随机访问以及在序列尾部进行快速插入和删除操作。
(2)双向访问:插入和删除所花费的时间是固定的,与位置无关。

4.定义与使用举例

可以在程序中这样来声明迭代器类型:

//容器类名::iterator 迭代器名;
vector<int>::iterator it;
#include<iostream>
#include<vector>
using namespace std;
int main (){
	vector <char> v;
	v.push_back('a'); //在容器尾部添加字母'a'
	v.push_back('b');
	v.push_back('c');
	v.push_back('d'); 
	for(int i=0;i<4; i++){
		cout<< " v[" << i << "] == " << v [i] <<endl;//对容器的访问
	}
	
	vector<char>::iterator it = v.begin(); //定义迭代器it并初始化为指向容器的超始位置
	cout<< "The third is " << v[2] <<endl;
	p++; //迭代器移向下一个数据项
	cout << *p <<endl; //输出第二个字母'b'
	p++;
	cout << *p <<endl;
	p--; //迭代器移向上一个数据项
	cout << *(p+2) <<endl; //输出'd'
	return 0;
}

输出结果:

v[0] == a
v[1] == b
v[2] == c
v[3] == d
The third is c
b
c
d
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值