STL学习总结

来源:互联网 发布:人工智能伏羲觉醒有2吗 编辑:程序博客网 时间:2024/06/10 17:26

STL学习总结

STL(Standard Template Library,标准模板库),是惠普实验室开发的一系列软件的统称。
STL从广义上分为:容器、算法、迭代器,容器和算法之间通过迭代器进行无缝连接。STL几乎所有的代码都采用了模板类或者模板函数,这相比传统的由函数和类组成的库来说提供了更好的代码重用机会

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 tempalte
STL六大组件的交互关系,容器通过空间配置器取得数据存储空间,算法通过迭代器存储容器中的内容,仿函数可以协助算法完成不同的策略的变化,适配器可以修饰仿函数。

STL优点

  • STL是C++的一部分,因此不用额外安装什么,它被内建在你的编译器之内。
  • STL的一个重要特点是数据结构和算法的分离。尽管这是个简单的概念,但是这种分离式得STL变得非常通用。例如:在STL的vector容器中,可以放入元素、基础数据类型变量、元素的地址;STL的sort()排序函数可以用来操作vector,list等容器
  • 程序员可以不用思考STL具体的实现过程,只要能够熟练使用STL就ol。这样他们就可以把精力放在程序开发的别的方面
  • STL具有高可重用性,高性能,高移植行,跨平台的优点。

STL容器就是将运用最广泛的一些数据结构实现出来,主要有数组(array)、链表(list)、树(tree),栈(stack),队列(queue),集合(set),映射表(map)。根据数据在容器的排列特性,这些数据分为序列式容器和关联式容器两种。

  • 序列式容器就是容器元素在容器中的位置是由元素进入容器的时间和地点来决定。vector、deque、list、stack、queue。
  • 关联式容器是指容器已经有了一定的规则,容器元素在容器的位置由我的规则来决定。set/multiset容器、map/multimap容器

算法分为:质变算法和非质变算法
质变算法:是指运算过程中会更改区间内的元素的内容。例如拷贝、替换、删除等
非质变算法:是指运算过程中不会更改区间内的元素内容,例如查找、计数、遍历、寻找极值等。
迭代器的种类:

种类 功能 支持方法 输入迭代器 提供对数据的只读访问 只读,支持++、==、!= 输出迭代器 提供数据的只写访问 只写,支持++ 前向迭代器 提供写操作,并能向前推进迭代器 读写,支持++、==、!= 双向迭代器 提供读写操作,并能向前和向后操作 读写,支持++、– 随机访问迭代器 提供读写操作,并能在数据中随机移动 读写,支持++、–、[n]、-n、<等

string容器

在C++标准库中定义了string类,定义在头文件<\string>
string和c风格字符串对比:

  • char* 是一个指针,string是一个类,string封装了char* ,管理这个字符串,是一个char*型的容器
  • string封装了很多实用的成员方法,比如查找find,拷贝copy,删除delete,替换replace,插入insert
  • 不用考虑内存释放和越界,string管理插入char*所分配的内存。每一次string的复制,取值都由string类负责维护,不用担心复制越界和取值越界等。

vector容器

vector的数据安排以及操作方式,与array(数组)非常相似,两者的唯一差别在于空间的运用的灵活性,array是静态空间,一旦配置了就不能改变,要换大一点或者小一点的空间,比较复杂。
vector的实现技术,关键在于其对大小的控制以及重新配置时的数据移动效率。其动态增加大小,并不是在原空间之后续接新空间(因为无法保证原空间之后尚有可配置的空间),而是取一块更大的内存空间,然后将原数据拷贝新空间,并释放原空间。因此,对vector的任何操作,一旦引起空间的重新配置,指向原vector的所有的迭代器就都失效了。
vector支持随机存取,所以vector提供的是随机访问迭代器

deque容器

vector容器是单向开口的连续内存空间,deque则是一种双向开口的连续性空间,所谓的双向开口,意思是可以在头尾两端分别做元素的插入和删除操作,当然,vector容器也可以在头尾两端插入元素,但是在其头部操作效率奇差,无法被接受。
deque和vector最大的差异,一在于deque允许使用常数项对头端进行元素的插入和删除操作。二是deque没有容量的概念,因为它是动态的以分段连续空间组合而成,随时可以增加一段新的空间链接起来。deque的迭代器并不是普通的指针,其复杂度和vector不是一个量级,这当然影响各个运算的层面。因此,除非有必要,我们应该尽可能的使用vector,而不是deque,对deque进行的排序操作,为了最高效率,可将deque先完整的复制到一个veector中,对vector容器进行拍下,在复制会deque。
deque是由一段一段的定量的连续空间构成,一旦有必要在deque前端和尾端增加新的空间,便配置一段连续定量的空间,串接在deque的头端或者尾端。deque最大的工作就是维护这些的分段连续的内存空间的整体性的假象,并提供随机存取的接口,避开了重新配置空间,复制,释放的轮回,代价就是复杂的迭代器架构。
既然deque是分段连续内存空间,那么就必须有中央控制,维持整体连续的假象,数据结构的设计及迭代器的前进后退操作颇为繁琐,deque代码的实现远比vector或list都多得多。
deque采取一块所谓的map(不是STL的map容器)作为主控,这里所谓的map是一小块连续的内存空间,其中每一个元素都是一个指针,只想另一段连续性内存空间,称为缓冲区,缓冲区才是deque的存储空间的主体。

stack容器

stack是一种先进后出的数据结构,它只有一个出口。stack容器允许新增元素,移除元素,取得栈顶元素,但是除了最顶端外,没有任何其他方法可以存取stack的其他元素。换言之,stack不允许有遍历行为。有元素推入栈的操作称为push,将元素推出stack的操作成为pop
stack所有元素的进出都必须符合“先进后出”的条件,只有stack顶端的元素,才有机会被外界去用,stack不提供遍历功能,也不提供迭代器。

queue容器

queue是一种先进先出的数据结构,它有两个出口,queue容器允许从一端新增元素,从另一端移除元素。
queue和stack容器一样,不提供遍历功能,也不提供迭代器。

list容器

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序通过链表中的指针链接次序实现的。链表由一系列结点组成。结点可以在运行时动态生成。每个结点包括两个部分:一个存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
相较于vector的连续线性空间,list就显得负责许多,它的好处是每次插入或者删除一个元素,就是配置或者释放一个元素的空间。因此,list对于空间的运用有着绝对的精准,一点也不浪费。而且,对于任何位置的元素插入或元素的移除,list永远是常数时间。
list和vector是两个最常被使用的容器。
list容器是一个双向链表。

  • 采用动态存储分配,不会造成内存浪费和溢出
  • 链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素
  • 链表灵活,但是空间和时间额外耗费较大

list容器不能想vector一样以普通指针作为迭代器,因为其节点不能保证在同一块连续的内存空间上。list迭代器必须有能力只想list的节点。并有能力进行正确的递增、递减、取值、成员存取操作。在递增的时候指向下一个节点,递减时指向上一个节点,取值时取得是节点的数据值,成员用时取的是节点的成员。
由于list是一个双向链表,迭代器必须能够具备前移、后移的能力,所以list容器提供的bidirectional itreators(双向)
list不仅是一个双向链表,而且还是一个循环的双向链表

set容器

set的特性就是所有的元素会根据元素的键值自动排序,set的元素不想map那样可以同时拥有实值和键值,set的元素既是键值又是实值,set不允许两个元素有相同的键值。
我们不能通过set的迭代器改变set元素的值,因为set元素值就是其键值,关系到set元素的排序规则,如果任意改变set元素值,会严重破坏set组织,set的iterator是一种const_iterator
set拥有和list某些相同的性质,当对容器中的元素进行插入操作或者删除操作的时候,操作之前所有的迭代器,在操作完成之后依然有效。
multiset容器特性及用法和set完全相同,唯一差别在于它允许键值重复,set和multiset的底层实现是红黑树,红黑树为平衡二叉树的一种。

map容器

map的特性是,所有的元素都会根据元素的键值自动排序,map所有的元素都是pair,同时拥有实值和键值,pair的第一元素被视为键值,第二元素被视为实值,map不允许两个元素有相同的键值。
我们不可以通过map的迭代器改变map的键值,因为map的键值关系到map元素的排列规则,任意改变map键值会严重破环map组织,如果想要修改元素的实值,那么是可以的。
map和list拥有相同的某些性质,当对它的容器元素进行新增操作或者删除操作时,操作之前的所有的迭代器,在操作完成之后依然有效。
multimap和map的操作类似,唯一区别multimap键值可重复
map和multimap都是以红黑树为底层实现机制。
STL容器所提供的都是值寓意,而非引用寓意,也就是当我们给容器中插入元素的时候,容器内部实施了拷贝动作,将我们要插入的元素再另行拷贝一份放入到容器当中,而不是将原数据直接放入容器当中,也就是说我们提供的元素必须能够被拷贝的。

STL容器使用时机

vector deque list set multiset map multimap 典型内存结构 单端数组 双端数组 双向链表 二叉树 二叉树 二叉树 可随机存取 是 是 否 否 否 对key而言:不是 元素搜寻速度 慢 慢 非常慢 快 快 对key而言:快 元素安插移除 尾端 头尾两端 任何位置 - - -
原创粉丝点击