STL学习笔记

STL(Standard Template Library)里有很多组成部分,但是主要有三个,容器、迭代器和算法

容器用来管理某个特定对象的集合。每一种容器都有自己的优点和缺点,在项目中根据不同的需求,使用不同的容器。容器可以是数组、链表或者类字典。

迭代器用于遍历对象集合的元素。这些集合可以是容器或容器的子集。每一个容器类都提供了它自己的迭代器类型。

算法用来处理的元素的集合。例如,可以进行搜索、排序等操作。

STL的数据和操作是分离的。数据存储在容器里,使用算法进行操作。迭代器是这两者之间的粘合剂,让算法与容器可以进行交互。

某种程度上,STL的概念与面向对象编程的原则相背,

STL数据和算法是分离的而不是结合。STL是泛型编程的一个很好的例子。容器和算法分别是任意类型和类的泛型。STL提供了更通用的组件。还可以通过使用适配器和仿函数来达到特殊要求。

容器

容器管理着一系列元素,为了满足不同的需求,STL提供了多种类型的容器,见下图。

主要可以分为三大类

序列容器是有序集合,其中的每个元素都有特定位置。这个位置取决于插入的时间和地点,但是它跟元素的值无关。STL包含5个预定义的序列容器类:array、vector、deque、list和forward_list。

关联容器是把元素的值按照某种规则排好顺序的集合。STL包含4个预定义的关联容器类:set、multiset、map和multimap。

无序(关联)容器是无序集合。主要关注一个元素是否在集合中。不论是插入的顺序还是插入元素的值对元素的位置都没有任何影响。STL包含4个预定义的无序容器类:unordered_set、unordered_multiset、unordered_map和unordered_multimap。

序列容器通常是数组或链表的实现

关联容器通常是二叉树的实现

无序容器通常是哈希表的实现

容器适配器

容器适配器提供顺序容器的特殊接口

stack 堆栈适配器(LIFO)

queue 改写容器来提供队列(FIFO数据结构)

priority_queue 改写容器来提供优先级队列

迭代器

根据迭代器所支持的操作,一般分为下面5种。

前向迭代器只能利用递增运算符进行前向迭代。像unordered_set、unordered_multiset、unordered_map和unordered_multimap这些容器都“至少”是用前向迭代器(某些情况下可以提供双向迭代器)。

双向迭代器是可以用递增运算符向前迭代,或者用递减运算符向后迭代。像list、set、multiset、map和multimap的迭代器都是双向迭代器。

随机访问迭代器具有双向迭代器的所有属性。此外,他们还可以进行随机访问。这种迭代器本身支持运算操作,可以改变偏移量,也可以利用关系运算符(< 和 >)比较迭代器。像vector、deque、array和string的迭代器都是这类迭代器。

输入迭代器能够在迭代时读取或处理一些值。如Input stream iterators。

输出迭代器能够在迭代时输出一些值。如Inserters、和output stream iterators。

算法

STL提供了一些标准算法来处理集合元素。这些算法一般提供最基本的功能,如搜索、排序、复制、修改和数值处理。

算法不是容器类的成员函数,而是全局函数。算法可以操作不同容器类型的元素,甚至可以操作用户自定义的容器类型。总之,既减少了代码量,又增强了性能。

迭代器适配器

任何操作起来像迭代器的东西都可以当作迭代器。所以可以写出像迭代器的一些类但又执行不一样的操作。C++标准库提供的一些预定义的特殊迭代器,即迭代器适配器。

一般分为四类:

Insert iterators也称为inserters,用来将“赋值新值”操作转换为“安插新值”操作。通过这种迭代器,算法可以执行安插(insert)行为而非覆盖(overwrite)行为。所有Insert迭代器都隶属于Output迭代器类型,所以它只提供赋值(assign)新值的能力。通常算法会将数值赋值给目的迭代器,如copy()算法

Stream iterators是一种迭代器配接器,可以把stream当成算法的原点和终点。更明确的说,一个istream迭代器可以用来从input stream中读元素,而一个ostream迭代器可以用来对output stream写入元素。Stream迭代器的一种特殊形式是所谓的stream缓冲区迭代器,用来对stream缓冲区进行直接读取和写入操作。

Reverse iterators重新定义递增运算和递减运算,使其行为正好倒置。

Move iterators很像一个底层迭代器(必须至少有一个InputIterator)。如果这个迭代器被当作输入迭代器来用,要注意的是,值的操作是移动而不是复制。

重点介绍向量:

向量容器使用动态数组存储、管理对象。因为数组是一个随机访问数据结构,所以可以随机访问向量中的元素。在数组中间或是开始处插入一个元素是费时的,特别是在数组非常大的时候更是如此。然而在数组末端插入元素却很快。

实现向量容器的类名是vector(容器是类模板)。包含vector类的头文件名是vector。所以,如果要在程序里使用向量容器,就要在程序中包含下面语句:

#include

此外,在定义向量类型对象时,必须指定该对象的类型,因为vector类是一个类模板。例如,语句:

vector intList;

将intList声明为一个元素类型为int的向量容器对象。类似地,语句:

vector stringList;将stringList声明为一个元素类型为string的向量容器对象。

声明向量对象

vector类包含了多个构造函数,其中包括默认构造函数。因此,可以通过多种方式来声明和初始化向量容器。表一描述了怎样声明和初始化指定类型的向量容器。

表一     各种声明和初始向量容器的方法

语句作用

vector vecList;创建一个没有任何元素的空向量vecList(使用默认构造函数)

vector vecList(otherVecList)创建一个向量vecList,并使用向量otherVecList中的元素初始化该向量。向量vecList与向量otherVecList的类型相同

vector vecLIst(size);

创建一个大小为size的向量vecList,并使用默认构造函数初始化该向量

vector vecList(n,elem);创建一个大小为n的向量vecList,该向量中所有的n个元素都初始化为elem

vector vecList(begin,end);创建一个向量vecList,并初始化该向量(begin,end)中的元素。即,从begin到end-1之间的所有元素

在介绍了如何声明向量顺序容器之后,让我们开始讨论如何操作向量容器中的数据。首先,必须要知道下面几种基本操作:

元素插入

元素删除

遍历向量容器中的元素

假设vecList是一个向量类型容器。表二给出了在vecList中插入元素和删除元素的操作,这些操作是vector类的成员函数。表二还说明了如何使用这些操作。

表二     向量容器上的各种操作

语句作用

vecList.clear()从容器中删除所有元素

vecList.erase(position)删除由position指定的位置上的元素

vecList.erase(beg,end)删除从beg到end-1之间的所有元素

vecList.insert(position, elem)将elem的一个拷贝插入到由position指定的位置上,并返回新元素的位置

vecList.inser(position, n, elem)将elem的n个拷贝插入到由 position指定的位置上

vecList.insert(position, beg, end)将从beg到end-1之间的所有元素的拷贝插入到vecList中由position指定的位置上

vecList.push_back(elem)将elem的一个拷贝插入致List的末尾

vecList.pop_back()删除最后元素

vecList.resize(num)将元素个数改为num。如果size()增加,默认的构造函数负责创建这些新元素

vecList.resize(num, elem)将元素个数改为num。如果size()增加,默认的构造函数将这些新元素初始化为elem

在向量容器中声明迭代器

vector类包含了一个typedef iterator,这是一个public成员。通过iterator,可以声明向量容器中的迭代器。例如,语句:

vector::iterator intVeciter;        将intVecIter声明为int类型的向量容器迭代器。

因为iterator是一个定义在vector类中的typedef,所以必须使用容器名(vector)、容器元素类型和作用域符来使用iterator。

表达式:

++intVecIter

将迭代器intVecIter加1,使其指向容器中的下一个元素。表达式:*intVecIter

返回当前迭代器位置上的元素。

注意,迭代器上的这些操作和指针上的相应操作是相同的。运算符*作为单目运算符使用时,称为递引用运算符。

下面将讨论如何使用迭代器来操作向量容器中的数据。假设有下面语句:

vector intList;

vector::iterator intVecIter;

第一行中的语句将intList声明为元素为int类型的向量容器。第二行中的语句将intVecIter声明为元素为int类型的向量容器的迭代器。

容器与函数begin和end

所有容器都包含成员函数begin和end。函数begin返回容器中第一个元素的位置;函数end返回容器中最后一个元素的位置。这两个函数都没有参数。在执行下面语句:

intVecIter = intList.begin();

迭代器intVecIter指向容器intList中第一个元素。

下面的for循环将intList中所有元素输出互标准输出设备上:

for (intVecIter = intList.begin(); intVecIter != intList.end();

cout<<*intVecList<<"     ";

可以通过表三中给出的操作直接访问向量容器中的元素。

表三 访问向量容器中元素的操作

表达式作用

vecList.at(index)返回由index指定的位置上的元素

vecList[index]返回由index指定的位置上的元素

vecList.front()返回第一个元素 (不检查容器是否为空)

vecList.back()返回最后一个元素(不检查容器是否为空)

表三说明:可以按照数组的方式来处理向量中的元素(注意,在C++中,数组下标从0始。,向量容器中第一个元素的位置也是0)。

徽号类中还包含:返回容器中当前元素个数的成员函数,返回可以插入到容器中的元素的最大个数的成员函数等。表四描述其中 一些操作(假设vecCont是向量容器)。

表四 计算向量容器大小的操作

表达式作用

vecCont.capacity()返回不重新分配空间可以插入到容器vecCont中的元素的最大个数

vecCont.empty()容器vecCont为空,返回true;否则,返回false

vecCont.size()返回容器vecCont中当前的个数

vecCont.max_size()返回可以插入到容器vecCont中的元素的最大个数

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,290评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,107评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,872评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,415评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,453评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,784评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,927评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,691评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,137评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,472评论 2 326
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,622评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,289评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,887评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,741评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,316评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,490评论 2 348

推荐阅读更多精彩内容

  • vector和string 所有的STL容器都很有用,但是相比于其他容器,vector和string更常用。本章从...
    lintong阅读 1,279评论 0 3
  • 容器 条款1:仔细选择你的容器 C++提供了很多可供程序员使用的容器:(1) 标准STL序列容器:vector,...
    lintong阅读 879评论 0 3
  • 迭代器 标准STL容器提供了四种不同的迭代器:iterator、const_iterator、reverse_it...
    lintong阅读 316评论 0 1
  • STL算法部分主要由头文件,,组成。要使用STL中的算法函数必须包含头文件,对于数值算法须包含,中则定义了一些模板...
    eb51589b1211阅读 601评论 0 1
  • 标签(空格分隔): STL 运用STL,可以充分利用该库的设计,让我为简单而直接的问题设计出简单而直接的解决方案,...
    认真学计算机阅读 1,471评论 0 10