概念
库是一系列程序组件的集合,它们可以在不同的程序中重复使用。
库函数设计的第一位的要求就是通用性,而模板为通用性带来了不可估量的前景。
STL库是C++中最有特色最实用的部分之一。
STL中包含的东西
我们将STL划分为6个组件。
一、容器类
我们又将容器划分为三个部分
1、顺序容器
(1)vector容器。它是一个矢量容器,它的底部是一个数组。是对顺序表进行了封装。
头文件:#include
(2)list容器。它也是双向链表容器。它的底部是一个双向链表(环状)。所以它的底部是一个双向循环列表。
头文件:#include
(3)deque容器。它是一个双端队列容器。它的底部放的是一个双端队列。
头文件:#include
2、关联容器
关联容器是由红黑树组成。
(1)set容器。又称单集合容器。它的底部是红黑树。
头文件:#include
(2)multiset容器。又称多重集合容器。它的底部也是红黑树。
头文件:#include
(3)map容器。又称单映射容器。它的底部也是红黑树。
头文件:#include
(4)multimap容器。又称多重映射容器。它的底部同样也是红黑树。
头文件:#include
3、容器适配器
(1)stack
(2)queue
(3)priority_queue
这三者都是由容器适配器来实现的。它的底层放的是一个容器。默认放的是deque容器。
二、泛型算法
泛型算法和容器的关系:容器如果当成数据结构来理解的话它是来存储数据的。如果我们要对这些数据进行一系列的操作的话像增删改查这样的操作。都是以泛型算法的方式实现的。泛型算法的好处就是,他已经与类型无关,底层不管放的是什么容器,都可以对其进行操作。
三、迭代器
一种针对于容器对象的遍历方式。
容器,泛型算法和迭代器三者之间的关系:首先,容器我们可以理解为数据,泛型算法是对数据进行的操作。这样看来数据和操作是分离开来进行设计的。那我们如何将它们又结合在一起,让泛型算法来操作容器里面的数据呢?那么就需要用到一个粘合剂,这个粘合剂就是迭代器它们的关系如下图所示:
迭代器的划分如下:
1、预定义
(1)输入型
(2)输出型
(3)正向迭代器
(4)双向迭代器
(5)随机访问型迭代器
2、功能
(1)反转型迭代器
(2)插入型迭代器
(3)流式迭代器
四、函数对象(仿函数)
1、一元函数对象
2、二元函数对象
五、适配器
1、取反器
2、绑定器
六、空间配置器
1、一级空间配置器
2、二级空间配置器
容器类
一、vector容器的实现
int main()
{
std::vector<int> vec1;
std::vector<int> vec2(10);
std::vector<int> vec3(10,20);
int arr[] = {1,3,21,43,6};
int len = sizeof(arr) / sizeof(srr[0]);
std::vector<int> vec4(arr, arr+len);//第一个有效元素的起始位置到第一个失效元素的起始位置.通过迭代器的方式传入元素空间
std::vector<int>::iterator it = vec4.begin();
while(it != vec4.end())
{
std::cout << *it << "";
}
std::cout << std::endl;
return 0 ;
}
由以上代码我们可以总结出,vector容器共有以下四个默认的构造函数。
1、默认的构造
std::vector<int> vec1;
2、int的构造。只代表大小
std::vector<int> vec2(10);
3、两个int的构造。第一个元素代表大小,第二个元素代表数值。
std::vector<int> vec3(10,20);
4、迭代器区间的构造。传入起始位置(frist)和末尾位置(last)。
std::vector<int> vec4(arr, arr+len);
二、对vector容器进行的操作
也就是增删改查的操作。
1、vector容器的插入方式
尾插和头插的方式
int main()
{
std::vector<int> vec;
for(int i = 0; i < 5;i++)
{
vec.push_back(i + 1);//尾插
}
std::vector<int>::iterator it = vec.begin() + 2;
vec.insert(it,100);
std::vector<int>::iterator it1 = vec.begin();
while(it1 != vec.end())
{
std::cout << *it1 << "";
itl++;
}
std::count << std::endl;
return 0;
}
三个按位置插入的方法:
(1)insert(_where, _First, _Last);//迭代器的位置和元素的区间
(2)insert(_where, count,val);//给定一个位置,给定个数,给定内容
(3)insert(_where,val);//给定一个位置,给定一个数据
2、vector容器的删除方式
int main()
{
std::vector<int> vec;
for(int i = 0; i < 5;i++)
{
vec.push_back(i + 1);//尾插
}
std::vector<int>::iterator it = vec.begin() + 2;
vec.insert(it,100);
std::vector<int>::iterator it1 = vec.begin();
while(it1 != vec.end())
{
std::cout << *it1 << "";
itl++;
}
std::count << std::endl;
vec.pop_back();
vec.erase(vec.begin(), vec.begin + 2);//按位置删除
}
按位置删除的两种方式:
(1)erase(_First,_Last);//删除区间的元素
(2)erase(_where);//删除位置上的元素
3、vector容器的优缺点
(1)优点:vector容器支持尾部快速的插入或者删除,它可以直接访问任何元素
(2)缺点:按位置插入和按位置删除元素的时候效率很差。
4、vector容器的扩容机制
vector容器的思想:是在内存足够的情况下,可以无限得存储元素。
它的扩容方法是这样的:
- 以倍数的形式开辟更大的空间
- 旧的数据拷贝到新空间中
- 释放旧的空间
- 指向新的空间调整总大小
vector容器的一个简单应用
我们现在给出这样一个编程题:
输入元素并存储。写个函数查询某个元素对应的位置:1、找到返回当前的位置。2、找不到返回一个无效的位置。
结合泛型算法进行简单的实现。
代码实现:
template<typename Itr>
Itr Find(Itr _First, Itr _Last, const typename Itr::value_type& val)
{
for(_First; _First != _Last;++_First)
{
if(*First == val)
{
return _First;
}
}
return _First;
}
int main()
{
int arr[] = {1,23,234,35,57};
int len = sizeof(arr) / sizeof(arr[0]);
std::vector<int> vec(arr,arr+len);
std::vector<int>::iterator fit = Find(vec.begin(),vec.end(),10);
if(fit != vec.end())
{
std::cout << *fit << std::endl;
}
else
{
std::cout << "not exist!" << std::endl;
}
return 0;
}
发现程序可以运行成功:
我们发现找10这个数据是不存在的。程序会输出not exist!