STL学习总结(C++)(待完成)

概述

概念

  1. STL不是面向对象编程(OOP),而是泛型编程(generic programming)。OOP关注的是编程的数据方面,而泛型编程关注的是算法。共同点是抽象和创建可重用代码。
  2. 泛型编程旨在编写独立于数据类型的代码。C++中完成通用程序的工具是模板。模板使得能够按泛型定义函数或类。模板使得算法独立于存储的数据类型。迭代器使算法独立于使用的容器类型。模板提供了存储在容器中的数据类型的通用表示,迭代器提供了遍历容器的值的通用表示。
  3. 常规指针就能满足迭代器的要求。
  4. 每个容器类定义了相应的迭代器类型,对于其中某个类,迭代器可能是指针,也可能是对象。
  5. 迭代器自动类型推断。auto
  6. 作为一种编程风格,最好避免直接使用迭代器,而尽可能使用STL函数(如for_each)来处理细节,也可以使用基于范围的for循环。
  7. 基于范围的for循环是用于STL而设计的。
    数据结构是数据的容器。
    在面向对象的世界里,数据结构是包含对象的对象。

STL内容

STL(Standard Template Library)是标准模板库,提供了一组表示容器、迭代器、函数对象、算法的模板。是对于list,stack,queue等其他数据结构的标准化模板化的对象容器库。

STL包括三个主要组件:容器,迭代器,算法。

STL容器包括最常用的和最重要的数据结构,它们都是模板化的,可以根据特定应用程序相关的数据类型进行调整。

STL特点

  1. STL不需要new和delete,而用分配器分配和释放空间。STL提供的默认分配器可以实现绝大多数要求(自定义分配器是高级课题,不必要掌握)。
  2. STL通常避免继承和虚函数,而使用模板化的常规编程——达到更好的性能。
  3. STL是容器编程的优选方法——提高代码的可移植性。
  4. STL的可拓展性——容易增加新算法而不改变STL容器。
STL异常类型说明
out_of_range表示下标超界
invalid_argument表示想函数传入了无效参数
length_error表示视图生成太长的容器、string等
bad_alloc表示用new(或分配器)分配内存失败,因为内存不足

组件一:容器

  1. 容器是存储其他对象的对象,被存储的对象必须是同一类型的。
  2. 容器存储的对象的类型必须是可复制构造的和可赋值的(如基本类型、类定义没有将复制构造函数和赋值运算符声明为私有或保护的)
  3. 存储在容器里的内容为容器所有,意味着在容器过期时,所有数据也过期。(如果数据是指针的话,它指向的数据不一定过期)
  4. 容器是一个与数组类似的单元,可以存储若干值,STL的容器是同质的,即存储的值的类型相同。
  5. 容器又分为三大类:顺序容器,关联容器,容器适配器。(顺序容器和关联容器统称为第一类容器)
  6. 容器类型:vector、list、deque、queue、priority_queue、forward_list、stack都是序列sequence。序列要求迭代器至少是正向迭代器,保证了元素将按特定顺序排列,不会在两次迭代之间发生变化。array也被归类为序列容器,虽然它不满足序列的所有要求。
  7. 序列要求元素按严格的线性顺序排序。数组和链表都是序列,但分支结构(其中每个节点都指向两个子节点)不是。
  8. 除此之外值得注意的还有一类:近容器(与第一类容器提供类似功能,但是没有提供第一类容器全部功能)。
容器vectordequelistsetmultisetmapmultimapstackqueuepriority_queue
简介顺序容器,动态数组顺序容器,双向队列顺序容器,双向链表关联容器,集合关联容器,多重集合关联容器,映射关联容器,多重映射容器适配器,堆栈容器适配器,队列容器适配器,优先级队列
特点从后面快速插入与删除,直接访问任何元素从前面或后面快速插入与删除,直接访问任何元素从任何位置快速插入和删除快速查找,不允许重复值快速查找,允许重复值一对一映射,基于关键字快速查找,不允许重复值一对多映射,基于关键字快速查找,允许重复值后进先出LIFO先进先出FIFO最高优先级元素总是第一个出列
特点1.内存地址连续
2.用于随机访问性能最佳
1.内存地址连续
迭代器类型随机访问迭代器随机访问迭代器双向迭代器双向迭代器双向迭代器双向迭代器双向迭代器不支持不支持不支持

在这里插入图片描述

1. 顺序容器

顺序容器包括了vector,deque,list,forward_list,array。以线性顺序存储一组类型相同的值。

  • 如果序列包含的元素个数是固定的:使用array,否则:使用vector
  • 经常在序列中间添加元素:使用list、forward_list
  • 经常在序列两端添加和删除元素:使用deque
a.emplace()
a.insert()
a.resize()
a.assign()
a.erase()
a.clear()
a.front()
a.back()
a.push_back()/a.push_front()
a.pop_back()/a.pop_front()
a.emplace_back()/a.emplace_front()
a[n]
a.at(n)

//vector
a.capacity()
a.reserve()

//list
a.splice()
a.remove()
a.remove_if()
a.unique()
a.merge()
a.sort()
a.reverse()

//forward_list的操作与list类似,但由于迭代器不能后移,因此用insert_after()、erase_after()、splice_after()替代了insert()、erase()、splice(),这些方法都对迭代器后面而不是前面的元素进行操作。

通过插入或删除的地方来选择容器

  • 在末尾插入\删除数据:vector
  • 在头尾插入\删除数据:deque
  • 在任意位置插入\删除数据:list

1.1 vector

特点:

  1. vector
  2. vector内存用完时,会自动分配更大的连续内存区(默认为原先大小的2倍),将原先的元素复制到内存区,释放旧的内存区。
  3. vector提供了连续内存地址,因此能用下标运算符[]来访问任何元素(同普通数组一样)
  4. vector支持随机访问迭代器,其迭代器通常实现为vector元素的指针。

详细用法:https://blog.csdn.net/qq_42132398/article/details/88580563

1.2 deque

详细用法:https://blog.csdn.net/qq_42132398/article/details/88599488

1.3 list

特点:

  1. list类是个双链表(每个节点包含上一节点和下一节点的指针)

详细用法:https://blog.csdn.net/qq_42132398/article/details/88584229

2. 关联容器

2.1 关联容器

  1. 关联容器的优点:它提供了对元素的快速访问。与序列相似,关联容器也允许插入新元素,但不能指定元素的插入位置。原因是关联容器有用于确定数据放置位置的算法,以便能够快速检索信息。
  2. 关联容器通常是使用某种树实现的,树是一种数据结构,查找速度比链表快。
  3. 关联容器将键看作常量,因此begin()返回的迭代器是常量迭代器,不能用作输出迭代器

(集合和映射是这种容器的模型)带有模板参数Key和Compare,分别表示用来对内容进行排序的键类型和用于对键值进行比较的函数对象。

对于set/multiset:存储的键=存储的值
对于map/multimap:存储的值与键类型相关联,值类型为pair

//关联容器
a.insert()
a.erase()
a.clear()
a.find()
a.count()
a.lower_bound()
a.upper_bound()
a.equal_range()
a.operator[ ] //仅限于map

//无序关联容器
a.insert()
a.erase()
a.clear()
a.find()
a.count()
a.operator[ ] //仅限于map

a.hash_function()
a.key_eq()
a.bucket_count()
a.max_bucket_count()
a.bucket()
a.begin()/a.cbegin()
a.end()/a.cend()
a.load_factor(); //返回每个桶包含的平均元素数
a.max_load_factor(); //返回负载函数的最大可能取值
a.rehash()
a.reserve()

2.1.1 set和multiset

见:https://blog.csdn.net/qq_42132398/article/details/88610156

2.1.2 map和multimap

见:https://blog.csdn.net/qq_42132398/article/details/88610157

2.2 无序关联容器

  1. 无序关联容器:关联容器是基于树结构的,无序关联容器是基于数据结构hash表的,旨在提高添加和删除元素的速度、提高查找算法的效率。
  2. 4种无序关联容器:unorder_set、unorder_multiset、unorder_map、unorder_multimap。

3. 容器适配器

3.1 stack

见:https://blog.csdn.net/qq_42132398/article/details/88625406

3.2 queue

见:https://blog.csdn.net/qq_42132398/article/details/88629053

3.3 priority_queue

见:https://blog.csdn.net/qq_42132398/article/details/88629053

4. 近容器

4.1 bitset

见:https://blog.csdn.net/qq_42132398/article/details/88653277

4.2 array

见:

4.3 valarray

见:

组件二:迭代器

迭代器能够用来遍历容器的对象,与能够遍历数组的指针相似,是广义指针。

  1. 输入迭代器:被程序用来读取容器中的信息。对输入迭代器解除引用将使程序能够读取容器中的值,但不一定能让程序修改值。因此,需要输入迭代器的算法不会修改容器的值。输入迭代器被递增后,不能保证其先前的值仍然可以被解除引用,即single-pass单通行的,不依赖于前一次遍历时的迭代器值,也不依赖于本次遍历中前面的迭代器值。输入迭代器是单向迭代器,可以递增,但不能倒退。应用:单通行,只读算法。
  2. 输出迭代器:对输出迭代器解除引用将使程序能够修改容器值,而不能读取。应用:单通行,只写算法。
  3. 正向迭代器:与输入和输出迭代器一样,只使用++运算符来遍历容器。与输入和输出不同的是,它总是按相同的顺序遍历一系列值,另外将正向迭代器递增后,仍然可以对前面的迭代器值接触引用(如果保存了它),并可以得到相同的值。正向迭代器既可以读写数据,又可以只读数据。应用:多通行算法。
  4. 双向迭代器:具有正向迭代器的所有特性,且同时支持前缀、后缀递减运算符。
  5. 随机访问迭代器:具有双向迭代器的所有特性,且添加了支持随机访问的操作和用于对元素进行排序的关系运算符。

迭代器功能:

  • 输入迭代器:解除引用读取、++i/i++
  • 输出迭代器:解除引用写入、++i/i++
  • 正向迭代器:解除引用读取和写入、++i/i++、固定和可重复排序
  • 双向迭代器:正向的所有、–i/i–
  • 随机访问迭代器:双向的所有、i[n]、i+n/i-n、i+=n/i-=n

为何需要这么多迭代器:为了在编写算法尽可能使用要求最低的迭代器,并让它适用于容器的最大区间。

各种迭代器的类型并不是确定的,而是一种概念性描述。概念可以具有类似继承的关系,然而不能将C++继承机制用于迭代器。

概念的具体实现被称为模型model。

将指针用作迭代器,迭代器是广义指针。指针满足所有的迭代器要求。迭代器是STL算法的接口,而指针是迭代器,因此STL算法可以使用指针来对基于指针的非STL容器进行操作,例如将STL算法用于常规数组。

ostream_iterator模板是输出迭代器概念的一个模型,是一个适配器——一个类或函数。

//out_iter迭代器是一个接口,能够使用cout来显示信息
#include<iterator>
ostream_iterator<int,char> out_iter(cout, " "); //int是输入流类型,char是输出流类型

istream_iterator:
reverse_iterator:
back_insert_iterator:将元素插入到容器尾部(条件是容器允许在尾部插入)
front_insert_iterator:将元素插入的容器头部(条件是容器允许在头部插入)
insert_iterator:将元素插入到指定位置之前

rbegin()和end()返回相同的值,但类型不同reverse_iterator和iterator。同理rend()和begin()。

反向指针的补偿:通过先递减,再解除引用。(如果p指向位置6,那么*p是位置5的值)

在显示声明迭代器和使用STL函数来处理内部问题上,选后者。
copy()不能自动根据发送值调整目标容器的长度。

在这里插入图片描述
特点:

  1. 用于指向第一类容器(vector/deque/list/set/multiset/map/multimap)
  2. 数组的指针可以在大多数STL算法中代替迭代器
    而其中只有vector和deque支持随机访问迭代器,其他只支持双向迭代器。

STL中预定义的四种迭代器类型:iterator,const_iterator,reverse_iterator,const_reverse_iterator

能用const_iterator的时候不要用iterator,这是最低权限原则一个例子。


组件三:算法

  1. STL算法库由和支持,提供了大量的基于迭代器的非成员模板函数。
  2. C++标准将算法分为4组:非修改式序列操作、修改式序列操作、排序、相关运算符和数值操作(C++将数值操作移到了numeric库中)。
  3. 算法是完成特定任务的处方。
  4. STL的重要性体现在能提供在各种容器中通用的算法。STL提供了70种左右的标准算法
  5. 特点:
    STL算法可以处理STL容器和基于指针的C语言式数组。
    STL算法是通过迭代器间接处理容器,因此一个算法可以用于多个不同的容器。

常用算法

1. 非变化序列算法

equal(),find(),count(),search()

2. 变化序列算法

copy(),reverse_copy(),remove_copy(),remove_copy_if()
remove(),remove_if()
replace()
fill()
swap()
reverse()
patition()
unique()

3. 数字型算法(头文件)

accumulate(),inner_product(),partial_sum(),adjacent_difference()
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值