STL的概念
什么是STL?
STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且 是一个包罗数据结构与算法的软件框架。
- STL从广义上分为:容器(container),算法(algorithm),迭代器(iterator),容器和算法之间通过迭代器进行无缝连接。STL几乎所有的代码都采用了模板类或者模板函数,这相比传统的由函数和类组成的库来说提供了更好的代码重用机会。STL(Standard Template Library)标准模板库,在我们c++标准库中隶属于STL的占到了80%。
STL六大组件简介
STL提供了六组件,彼此之间可以组合套用,这六大组件分别是:容器,算法,迭代器。仿函数,适配器(配接器),空间配置器。
- 容器:各种数据结构,如vector,list,deque,set,map等,用来存访数据,从实现角度来看,STL容器是一种
class template
- 算法:各种常用的算法,如sort,find,copy,for_each.从实现的角度看,STL的算法是一种
function tempalte
- 迭代器:扮演了容器与算法之间的胶合剂,共有五种类型,从实现角度来看,迭代器是一种operator*,operator->,operator++,operator–等指针相关操作予以重载的class template。所有STL容器都附带有自己专属的迭代器,只有容器的设计者才知道如何遍历自己的元素。原生指针也是一种迭代器。
- 仿函数:行为类似函数,可作为算哒的某种策略。从实现角度来看,仿函数是一种重载了operator()的class或者class template
- 适配器:一种用来修饰容器或者仿函数或迭代器接口的东西
- 空间配置器:负责空间的配置与管理。从实现角度看,配置器是一个实现了动态空间配置,空间管理,空间释放的
class template
STL六大组件的交互关系,容器通过空间配置器取得数据存储空间,算法通过迭代器存储容器中得内容,仿函数可以协助算法完成不同的策略的变化,适配器可以修饰仿函数。
STL的优点
- STL是c++的一部分,因此不用额外安装什么,它被内建在你的编译器之内。
- STL的一个重要特征是将数据和操作分离。数据由容器类别加以管理,操作则由可定制的算法定义。迭代器在两者之间充当“粘合剂”,以使算法可以和容器交互运作
- 程序员可以不用思考STL具体的实现过程,只要能够熟练使用STL就OK了。这样他们就可以把精力放在程序开放的别的方面
- STL具有高可重用性,高性能,高移植性,跨平台的优点
高可重用性 STL中几乎所有的代码都采用了模板类和模板函数的方式实现,这相比传统的由函数和类组成的库来说提供了更好的代码重用机会。
高性能:如map可以高效地从十万条记录里面查找指定的记录,因为map是采用红黑树的变体实现的
高移植性性:如在项目A上用STL编写的模块,可以直接移植到项目B上
三大组件
容器:
常用的数据结构:数组(array),链表(list),tree(树),栈(stac)队列(queue),集合(set),映射表(map),根据数据在容器中的排列特性,这些数据分为序列式容器和关联式容器两种
- 序列式容器强调值得排序,序列式容器中得每个元素均有固定得位置,除非用删除或插入得操作改变这个位置。Vector容器,Deque容器,List容器等。
- 关联式容器是非线性得数结构,更准确得说是二叉树结构,各元素之间没有严格的物理上得顺序关系,也就是说元素在容器中并没有保存元素置入容器时的逻辑顺序,关联式容器另一个显著特点是:在值中选择一个值作为关键字key,这个关键字对值起到索引的作用,方便查找。Set/multiset容器-Map/mulitimap容器
算法:
广义而言,我们所编写的每个程序都是一个算法,其中的每个函数也是一个算法,毕竟它们都是用来解决或大或小的逻辑问题或数学问题。STL收录的算法经过了数学上的效能分析与证明,是极具复用价值的,包括常用的排序,查找等等。特定的算法往往搭配特定的数据结构,算法与数据结构相辅相成。
3. 算法分为:质变算法和非质变算法
4. 质变算法:是指运算过程中会更改区间内的元素的内容。例如拷贝,替换,删除等等
5. 非质变算法:是指运算过程中不会更改区间内的元素内容,例如查找,计数,遍历,寻找极值
再好的编程,也无法让一个笨拙的算法起死回生。
迭代器
依次寻访某个容器所含的各个元素
#include<iostream>
#include<string>
using namespace std;
#include<vector>
//使用系统算法的头文件
#include<algorithm>//容器 vector//迭代器 遍历功能 用指针理解
//普通的指针也算一种指针
void test01()
{int array[5] = { 1, 3, 5, 7, 8 };int * p = array;//指针指向数组首地址 &array[0]for (int i = 0; i < 5; i++){//cout << array[i] << endl;cout << *(p++) << endl;}}void myPrint(int v)
{cout << v << endl;
}void test02()
{//声明容器vector<int>v;//声明一个容器 这个容器中存放int类型数据 对象名称//向容器中加入数据v.push_back(10);v.push_back(20);v.push_back(30);v.push_back(40);//遍历容器中的数据//利用迭代器vector<int >::iterator itBegin = v.begin();//itBegin指向是v容器的起始位置vector<int >::iterator itEnd = v.end();//itEnd指向容器中最后一个位置的下一个地址/*while (itBegin!=itEnd){cout << *itBegin << endl;itBegin++;}*///第二种遍历方式//for (int i = 0; i < 10; i++)/*for (vector<int>::iterator it = v.begin(); it != v.end();it++){cout << *it << endl;}*///第三种方式 利用算法for_each(v.begin(), v.end(), myPrint);}//操作自定义 的数据类型
class Person
{
public:Person(string name,int age){this->m_Name = name;this->m_Age = age;}string m_Name;int m_Age;
};void test03()
{vector<Person >v;Person p1("大头儿子",10);Person p2("小头爸爸", 30);Person p3("隔壁王叔叔", 30);Person p4("围裙妈妈", 28);v.push_back(p1);v.push_back(p2);v.push_back(p3);v.push_back(p4);//遍历for (vector<Person>::iterator it = v.begin(); it != v.end(); it++){cout << "姓名:" << (*it).m_Name << "年龄:" << it->m_Age << endl;}}//存放自定义数据类型的指针
void test04()
{vector<Person *>v;Person p1("大头儿子", 10);Person p2("小头爸爸", 30);Person p3("隔壁王叔叔", 30);Person p4("围裙妈妈", 28);v.push_back(&p1);v.push_back(&p2);v.push_back(&p3);v.push_back(&p4);for (vector<Person*>::iterator it = v.begin(); it != v.end(); it++){cout << "姓名:" << (*it)->m_Name << "年龄:" << (*it)->m_Age << endl;}
}//容器嵌套容器
void test05()
{vector<vector<int>>v;vector<int>v1;vector<int >v2;vector<int >v3;for (int i = 0; i < 5; i++){v1.push_back(i);v2.push_back(i + 100);v3.push_back(i + 100);}//将小容器放入到大容器中v.push_back(v1);v.push_back(v2);v.push_back(v3);//遍历所有数据for (vector<vector<int>>::iterator it = v.begin(); it != v.end(); it++){for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end(); vit++){cout << *vit << " ";}cout << endl;}
}int main()
{//test01();//test02();//test03();//test04();test05();system("pause");return 0;
}