STL总结与常见面试题


STL总结与常见面试题

文章插图
 
1 STL概述为了建立数据结构和算法的一套标准,并且降低他们之间的耦合关系,以提升各自的独立性、弹性、交互操作性(相互合作性,interoperability),诞生了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容器都附带有自己专属的迭代器,只有容器的设计者才知道如何遍历自己的元素 。原生指针(native pointer)也是一种迭代器 。
  • 仿函数:行为类似函数,可作为算法的某种策略 。从实现角度来看,仿函数是一种重载了operator()的class 或者class template
  • 适配器:一种用来修饰容器或者仿函数或迭代器接口的东西 。
  • 空间配置器:负责空间的配置与管理 。从实现角度看,配置器是一个实现了动态空间配置、空间管理、空间释放的class tempalte.
STL六大组件的交互关系,容器通过空间配置器取得数据存储空间,算法通过迭代器存储容器中的内容,仿函数可以协助算法完成不同的策略的变化,适配器可以修饰仿函数 。
2 STL的优点:
  1. STL 是 C++的一部分,因此不用额外安装什么,它被内建在你的编译器之内 。
  2. STL 的一个重要特性是将数据和操作分离 。数据由容器类别加以管理,操作则由可定制的算法定义 。迭代器在两者之间充当“粘合剂”,以使算法可以和容器交互运作
  3. 程序员可以不用思考 STL 具体的实现过程,只要能够熟练使用 STL 就 OK 了 。这样他们就可以把精力放在程序开发的别的方面 。
  4. STL 具有高可重用性,高性能,高移植性,跨平台的优点 。
  5. 高可重用性:STL 中几乎所有的代码都采用了模板类和模版函数的方式实现,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会 。
  6. 高性能:如 map 可以高效地从十万条记录里面查找出指定的记录,因为 map 是采用红黑树的变体实现的 。
  7. 高移植性:如在项目 A 上用 STL 编写的模块,可以直接移植到项目 B 上 。容器和算法之间通过迭代器进行无缝连接 。STL 几乎所有的代码都采用了模板类或者模板函数,这相比传统的由函数和类组成的库来说提供了更好的代码重用机会 。
3 容器STL容器就是将运用最广泛的一些数据结构实现出来 。
常用的数据结构:数组(array) , 链表(list), tree(树),栈(stack), 队列(queue), 集合(set),映射表(map), 根据数据在容器中的排列特性,这些数据分为序列式容器和关联式容器两种 。
序列式容器强调值的排序,序列式容器中的每个元素均有固定的位置,除非用删除或插入的操作改变这个位置 。Vector容器、Deque容器、List容器等 。
关联式容器是非线性的树结构,更准确的说是二叉树结构 。各元素之间没有严格的物理上的顺序关系,也就是说元素在容器中并没有保存元素置入容器时的逻辑顺序 。关联式容器另一个显著特点是:在值中选择一个值作为关键字key,这个关键字对值起到索引的作用,方便查找 。Set/multiset容器 Map/multimap容器
STL总结与常见面试题

文章插图
 

STL总结与常见面试题

文章插图
 
array 是固定大小的顺序容器,它们保存了一个以严格的线性顺序排列的特定数量的元素 。
STL总结与常见面试题

文章插图
 

STL总结与常见面试题

文章插图
 
测试代码#include<IOStream>#include<array>using namespace std;int main() { array<int, 8> myArr = {1,3,4,6,9};//固定大小为8 cout << "myArr元素序列:"; for (auto i = 0; i < 8; ++i){cout << myArr[i] << " "; } cout << endl; array<int, 8> myArr1 = {2,3,4,7,8,9};//固定大小为8 cout << "myArr1元素序列:"; for (auto i = 0; i < 8; ++i){cout << myArr1[i] << " "; } cout << endl; myArr.swap(myArr1);//交换两个容器的内容 cout << "交换myArr与myArr1"<< endl; cout << endl; cout << "myArr.at(3) = " << myArr.at(3) << endl;//任意访问 cout << "myArr[3] = " << myArr[3] << endl;//任意访问 cout << "myArr.front() = " << myArr.front() << endl;//获取第一个元素 cout << "myArr.back() =" << myArr.back() << endl;//获取最后一个元素 cout << "myArr.data() = " << myArr.data() << endl;//获取第一个元素的指针 cout << "*myArr.data() = " << *myArr.data() << endl;//获取第一个元素的指针指向的元素 cout << "正向迭代器遍历容器:"; for (auto it = myArr.begin(); it != myArr.end(); ++it){cout << *it << " "; } cout << endl; //逆向迭代器测试 cout << "逆向迭代器遍历容器:"; for (auto rit = myArr.rbegin(); rit != myArr.rend(); ++rit){cout << *rit << " "; } cout << endl; //正向常迭代器测试 cout << "正向常迭代器遍历容器:"; for (auto it = myArr.cbegin(); it != myArr.cend(); ++it){cout << *it << " "; } cout << endl; //逆向常迭代器测试 cout << "逆向常迭代器遍历容器:"; for (auto rit = myArr.crbegin(); rit != myArr.crend(); ++rit){cout << *rit << " "; } cout << endl; if(myArr.empty())cout << "myArr为空 " << endl; elsecout << "myArr不为空 " << endl; cout << "myArr.size() = " << myArr.size() << endl; cout << "myArr.max_size() = " << myArr.max_size() << endl; return 0;}


推荐阅读