C++学习笔记-STL
C++ STL (Standard Template Library标准模板库) 是通用类模板和算法的集合,它提供给程序员一些标准的数据结构的实现如 queues(队列), lists(链表), 和 stacks(栈)等
导入
- 抽象的重要性
计算机科学的重要进步,许多是由于发掘了新的抽象性质而促成的
面向过程 -> 基于对象 -> 面向对象 -> 泛型 - 面向过程(Procedure-Oriented)的抽象
抽象出Procedure(Function)的概念,把程序分成若干个子过程。将事物的方法隐藏于各个函数内–C语言
适用于处理小型的程序。对大型程序,子程序之间关系复杂,不易处理变化的需求–引发软件危机的原因–需要新的抽象 - 基于对象(Object-Based)的抽象
引入抽象数据类型(ADT,Abstract Data Type)。C++的类,将事物的属性与方法紧密地结合在一起–VB、带类的C
与面向过程相比,可以更好地处理变化,一定程度上化解了软件危机。但各个类之间的关系不容易处理,而且程序代码数量比面向过程时更大–需要新的抽象 - 面向对象(Object-Oriented)的抽象
抽象出封装、继承、多态( polymorphic )的概念
与基于对象相比,有更多的间接性。运用多态,我们可以调用某种方法,而不用指定此方法所属的类型。因而达到更进一步的抽象性
它为我们带来了什么?--MFC(用面向对象技术封装Windows API,抽象出一个类体系) - 泛型(Generic)的概念
Generic是一种抽象 就如OO是一种抽象
还没有语法与之相对应–正在开发中。(Function、Class、D : public B)
它为我们带来了什么?–STL
STL的概念
- 何为STL
STL(Standard Template Library)是C++标准库的一部分(80%),是用C++ template机制来表达泛型的库
STL(Standard Template Library)是用泛型技术来设计完成的实例,就如MFC(Microsoft Foundational Classes)是用面向对象技术来设计完成的实例 - STL抽象的是什么
有些算法并不依赖于数据结构的特定实现,而只是依赖于该结构的几个基本的语义属性
STL抽象出这些基本属性(Concept),成功的将算法与数据结构分离,在没有效率损失的前提下,得到了及大的弹性
STL的组成
六大组件
- 容器(Container)
- 算法(Algorithm)
- 迭代器(Iterator)
- 仿函数(Function object)
- 适配器(Adaptor)
- 空间配制器(allocator)
顺序性容器
vector 从后面快速的插入与删除,直接访问任何元素
deque 从前面或后面快速的插入与删除,直接访问任何元素
list 双链表,从任何地方快速插入与删除
关联容器
set 快速查找,不允许重复值
multiset 快速查找,允许重复值
map 一对多映射,基于关键字快速查找,不允许重复值
multimap 一对多映射,基于关键字快速查找,允许重复值
容器适配器
stack 后进先出
queue 先进先出
priority_queue 最高优先级元素总是第一个出列
顺序性容器
vector(向量容器)
vector是一个线性顺序结构。相当于数组,但其大小可以不预先指定,并且自动扩展。它可以像数组一样被操作,由于它的特性我们完全可以将vector看作动态数组
在创建一个vector后,它会自动在内存中分配一块连续的内存空间进行数据存储,初始的空间大小可以预先指定也可以由vector 默认指定,这个大小即capacity()函数的返回值。当存储的数据超过分配的空间时vector会重新分配一块内存块,但这样的分配是很耗时的,在重新分配空间时它会做这样的动作:
- 首先,vector会申请一块更大的内存块
- 然后,将原来的数据拷贝到新的内存块中
- 其次,销毁掉原内存块中的对象(调用对象的析构函数)
- 最后,将原来的内存空间释放掉
如果vector保存的数据量很大时,这样的操作一定会导致糟糕的性能(这也是vector 被设计成比较容易拷贝的值类型的原因)。所以说vector不是在什么情况下性能都好,只有在预先知道它大小的情况下vector的性能才是最优的
vector的特点:
- 指定一块如同数组一样的连续存储,但空间可以动态扩展。即它可以像数组一样操作,并且可以进行动态操作。通常体现在push_back() pop_back()
- 随机访问方便,它像数组一样被访问,即支持[]操作符和vector.at()
- 节省空间,因为它是连续存储,在存储数据的区域都是没有被浪费的,但是要明确一点vector大多情况下并不是满存的,在未存储的区域实际是浪费的
- 在内部进行插入、删除操作效率非常低,这样的操作基本上是被禁止的。 Vector被设计成只能在后端进行追加和删除操作,其原因是vector内部的实现 是按照顺序表的原理
- 只能在vector的最后进行push和pop,不能在vector的头进行push和pop
- 当动态添加的数据超过vector默认分配的大小时要进行内存的重新分配、拷贝与释放,这个操作非常消耗性能。所以要vector达到最优的性能,最好在创建vector时就指定其空间大小
vectors包含着一系列连续存储的元素,其行为和数组类似。访问Vector中的任意元素或从末尾添加元素都可以在常量级时间复杂度内完成,而查找特定值的元素所处的位置或是在vector中插入元素则是线性时间复杂度
Constructors
构造函数
vector<int> v1; //构造一个空的vector
vector<int> v1(5, 42); //构造了一个包含5个值为42的元素的Vector
Operators对vector进行赋值或比较
C++ Vectors能够使用标准运算符:==
,!=
,<=
,>=
,<
, 和>
要访问vector中的某特定位置的元素可以使用[]操作符
两个vectors被认为是相等的,如果:
1.它们具有相同的容量
2.所有相同位置的元素相等
vectors之间大小的比较是按照词典规则assign()
对Vector中的元素赋值
语法:
void assign( input_iterator start, input_iterator end ); // 将区间[start, end)的元素赋到当前vector
void assign( size_type num, const TYPE &val ); // 赋num个值为val的元素到vector中,这个函数将会清除掉为vector赋值以前的内容
at()
返回指定位置的元素
语法:
TYPE at(size_type loc);//差不多等同v[i];但比v[i]安全;
back()
返回最末一个元素begin()
返回第一个元素的迭代器capacity()
返回vector所能容纳的元素数量(在不重新分配内存的情况下)clear()
清空所有元素empty()
判断Vector是否为空(返回true时为空)end()
返回最末元素的迭代器(译注:实指向最末元素的下一个位置)erase()
删除指定元素
语法:
iterator erase( iterator loc );//删除loc处的元素
iterator erase( iterator start, iterator end );//删除start和end之间的元素
front()
返回第一个元素的引用get_allocator()
返回vector的内存分配器insert()
插入元素到Vector中
语法:
iterator insert( iterator loc, const TYPE &val ); //在指定位置loc前插入值为val的元素,返回指向这个元素的迭代器
void insert( iterator loc, size_type num, const TYPE &val ); //在指定位置loc前插入num个值为val的元素
void insert( iterator loc, input_iterator start, input_iterator end ); //在指定位置loc前插入区间[start, end)的所有元素
max_size()
返回Vector所能容纳元素的最大数量(上限)pop_back()
移除最后一个元素push_back()
在Vector最后添加一个元素rbegin()
返回Vector尾部的逆迭代器rend()
返回Vector起始的逆迭代器reserve()
设置Vector最小的元素容纳数量
//为当前vector预留至少共容纳size个元素的空间resize()
改变Vector元素数量的大小
语法:
void resize( size_type size, TYPE val ); //改变当前vector的大小为size,且对新创建的元素赋值val
size()
返回Vector元素数量的大小swap()
交换两个Vector
语法:
void swap( vector &from );
List(双向链表)
是一个线性链表结构,它的数据由若干个节点构成,每一个节点都包括一个信息块(即实际存储的数据)、一个前驱指针和一个后驱指针。它无需分配指定的内存大小且可以任意伸缩,这是因为它存储在非连续的内存空间中,并且由指针将有序的元素链接起来。
由于其结构的原因,list随机检索的性能非常的不好,因为它不像vector那样直接找到元素的地址,而是要从头一个一个的顺序查找,这样目标元素越靠后,它的检索时间就越长。检索时间与目标元素的位置成正比。
虽然随机检索的速度不够快,但是它可以迅速地在任何节点进行插入和删除操作。因为list的每个节点保存着它在链表中的位置,插入或删除一个元素仅对最多三个元素有所影响,不像vector会对操作点之后的所有元素的存储地址都有所影响,这一点是vector 不可比拟的
list的特点:
- 不使用连续的内存空间这样可以随意地进行动态操作
- 可以在内部任何位置快速地插入或删除,当然也可以在两端进行push和pop
- 不能进行内部的随机访问,即不支持[]操作符和vector.at();Lists将元素按顺序储存在链表中,与向量(vectors)相比,它允许快速的插入和删除,但是随机访问却比较慢
assign()
给list赋值
语法:
void assign(input_iterator start, input_iterator end);//以迭代器start和end指示的范围为list赋值
void assign(size_type num, const TYPE &val);//赋值num个以val为值的元素
back()
返回最后一个元素的引用begin()
返回指向第一个元素的迭代器clear()
删除所有元素empty()
如果list是空的则返回trueend()
返回末尾的迭代器erase()
删除一个元素
语法:
iterator erase(iterator loc);//删除loc处的元素
iterator erase(iterator start, iterator end);//删除start和end之间的元素
front()
返回第一个元素的引用get_allocator()
返回list的配置器insert()
插入一个元素到list中
语法:
iterator insert(iterator loc, const TYPE &val);//在指定位置loc前插入值为val的元素,返回指向这个元素的迭代器
void insert(iterator loc, size_type num, const TYPE &val);//定位置loc前插入num个值为val的元素
void insert(iterator loc, input_iterator start, input_iterator end);//在指定位置loc前插入区间[start, end)的所有元素
max_size()
返回list能容纳的最大元素数量merge()
合并两个list
语法:
void merge( list &lst );//把自己和lst链表连接在一起
void merge( list &lst, Comp compfunction );//指定compfunction,则将指定函数作为比较的依据
pop_back()
删除最后一个元素pop_front()
删除第一个元素push_back()
在list的末尾添加一个元素push_front()
在list的头部添加一个元素rbegin()
返回指向第一个元素的逆向迭代器remove()
从list删除元素
语法:
void remove( const TYPE &val );//删除链表中所有值为val的元素
remove_if()
按指定条件删除元素rend()
指向list末尾的逆向迭代器resize()
改变list的大小
语法:
void resize(size_type num, TYPE val);//把list的大小改变到num。被加入的多余的元素都被赋值为val22.
reverse()
把list的元素倒转size()
返回list中的元素个数sort()
给list排序
语法:
void sort();//为链表排序,默认是升序
void sort(Comp compfunction);//采用指定函数compfunction来判定两个元素的大小
splice()
合并两个list
语法:
void splice(iterator pos, list &lst);//把lst连接到pos的位置
void splice(iterator pos, list &lst, iterator del);//插入lst中del所指元素到现链表的pos上
void splice(iterator pos, list &lst, iterator start, iterator end);//用start和end指定范围
swap()
交换两个list
语法:
void swap(list &lst);//交换lst和现链表中的元素
unique()
删除list中重复的元素
语法:
void unique();//删除链表中所有重复的元素
void unique(BinPred pr);//指定pr,则使用pr来判定是否删除
Deque(双向队列)
是一种优化了的、对序列两端元素进行添加和删除操作的基本序列容器。它允许较为快速地随机访问,但它不像vector把所有的对象保存在一块连续的内存块,而是采用多个连续的存储块,并且在一个映射结构中保存对这些块及其顺序的跟踪。向deque两端添加或删除元素的开销很小。它不需要重新分配空间,所以向末端增加元素比vector更有效。
实际上,deque是对vector和list优缺点的结合,它是处于两者之间的一种容器。
deque的特点:
- 随机访问方便,即支持[]操作符和vector.at(),但性能没有vector好
- 可以在内部进行插入和删除操作,但性能不及list
- 可以在两端进行push、pop
- 相对于verctor占用更多的内存
双向队列和向量很相似,但是它允许在容器头部快速插入和删除(就像在尾部一样)
Constructors
创建一个新双向队列
语法:
deque();//创建一个空双向队列
deque(size_type size);//创建一个大小为size的双向队列
deque(size_type num, const TYPE &val);//放置num个val的拷贝到队列中
deque(const deque &from);//从from创建一个内容一样的双向队列
deque(input_iterator start, input_iterator end);//start和end创建一个队列,保存从start到end的元素
Operators
比较和赋值双向队列
//可以使用[]操作符访问双向队列中单个的元素assign()
设置双向队列的值
语法:
void assign(input_iterator start, input_iterator end);//start和end指示的范围为双向队列赋值
void assign(Size num, const TYPE &val);//设置成num个val
at()
返回指定的元素
语法:
reference at(size_type pos);//返回一个引用,指向双向队列中位置pos上的元素
back()
返回最后一个元素
语法:
reference back();//返回一个引用,指向双向队列中最后一个元素
begin()
返回指向第一个元素的迭代器
语法:
iterator begin();//返回一个迭代器,指向双向队列的第一个元素
clear()
删除所有元素empty()
返回真如果双向队列为空end()
返回指向尾部的迭代器erase()
删除一个元素
语法:
iterator erase(iterator pos);//删除pos位置上的元素
iterator erase(iterator start, iterator end);//删除start和end之间的所有元素
//返回指向被删除元素的后一个元素
front()
返回第一个元素的引用get_allocator()
返回双向队列的配置器insert()
插入一个元素到双向队列中
语法:
iterator insert(iterator pos, size_type num, const TYPE &val);//pos前插入num个val值
void insert(iterator pos, input_iterator start, input_iterator end);//插入从start到end范围内的元素到pos前面
max_size()
返回双向队列能容纳的最大元素个数pop_back()
删除尾部的元素pop_front()
删除头部的元素push_back()
在尾部加入一个元素push_front()
在头部加入一个元素rbegin()
返回指向尾部的逆向迭代器rend()
返回指向头部的逆向迭代器resize()
改变双向队列的大小size()
返回双向队列中元素的个数swap()
和另一个双向队列交换元素
语法:
void swap(deque &target);//交换target和现双向队列中元素
三者比较
vector是一段连续的内存块,而deque是多个连续的内存块,list是所有数据元素分开保存,可以是任何两个元素没有连续。vector的查询性能最好,并且在末端增加数据也很好,除非它重新申请内存段;适合高效地随机存储。
list是一个链表,任何一个元素都可以是不连续的,但它都有两个指向上一元素和下一元素的指针。所以它对插入、删除元素性能是最好的,而查询性能非常差;适合大量地插入和删除操作而不关心随机存取的需求。
deque是介于两者之间,它兼顾了数组和链表的优点,它是分块的链表和多个数组的联合。所以它有被list好的查询性能,有被vector好的插入、删除性能。如果你需要随即存取又关心两端数据的插入和删除,那么deque是最佳之选。
关联容器
特点
set,multiset,map,multimap是一种非线性的树结构,具体的说采用的是一种比较高效的特殊的平衡检索二叉树——红黑树结构。(至于什么是红黑树,我也不太理解,只能理解到它是一种二叉树结构)
因为关联容器的这四种容器类都使用同一原理,所以他们核心的算法是一致的,但是它们在应用上又有一些差别,先描述一下它们之间的差别。
set又称集合,实际上就是一组元素的集合,但其中所包含的元素的值是唯一的,且是按一定顺序排列的,集合中的每个元素被称作集合中的实例。因为其内部是通过链表的方式来组织,所以在插入的时候比vector快,但在查找和末尾添加上比vector慢。
multiset是多重集合,其实现方式和set是相似的,只是它不要求集合中的元素是唯一的,也就是说集合中的同一个元素可以出现多次。
map提供一种“键-值”关系的一对一的数据存储能力。其“键”在容器中不可重复,且按一定顺序排列(其实我们可以将set也看成是一种键-值关系的存储,只是它只有键没有值。它是map的一种特殊形式)。由于其是按链表的方式存储,它也继承了链表的优缺点。
multimap和map的原理基本相似,它允许“键”在容器中可以不唯一。
关联容器的特点是明显的,相对于顺序容器,有以下几个主要特点:
- 其内部实现是采用非线性的二叉树结构,具体的说是红黑树的结构原理实现的
- set和map保证了元素的唯一性,mulset和mulmap扩展了这一属性,可以允许元素不唯一
- 元素是有序的集合,默认在插入的时候按升序排列
基于以上特点
- 关联容器对元素的插入和删除操作比vector要快,因为vector是顺序存储,而关联容器是链式存储;比list要慢,是因为即使它们同是链式结构,但list是线性的,而关联容器是二叉树结构,其改变一个元素涉及到其它元素的变动比list要多,并且它是排序的,每次插入和删除都需要对元素重新排序
- 关联容器对元素的检索操作比vector慢,但是比list要快很多。vector是顺序的连续存储,当然是比不上的,但相对链式的list要快很多是因为list是逐个搜索,它搜索的时间是跟容器的大小成正比,而关联容器查找的复杂度基本是Log(N),比如如果有1000个记录,最多查找10次,1,000,000个记录,最多查找20次。容器越大,关联容器相对list的优越性就越能体现
- 在使用上set区别于vector,deque,list的最大特点就是set是内部排序的,这在查询上虽然逊色于vector,但是却大大的强于list
- 在使用上map的功能是不可取代的,它保存了“键-值”关系的数据,而这种键值关系采用了类数组的方式。数组是用数字类型的下标来索引元素的位置,而map是用字符型关键字来索引元素的位置。在使用上map也提供了一种类数组操作的方式,即它可以通过下标来检索数据,这是其他容器做不到的,当然也包括set。(STL中只有vector和map可以通过类数组的方式操作元素,即如同ele[1]方式)
Sets & MultiSets
集合(Set)是一种包含已排序对象的关联容器。多元集合(MultiSets)和集合 (Sets)相像,只不过支持重复对象,其用法与set基本相同
begin()
返回指向第一个元素的迭代器clear()
清除所有元素count()
返回某个值元素的个数empty()
如果集合为空,返回trueend()
返回指向最后一个元素的迭代器equal_range()
返回第一个>=关键字的迭代器和>关键字的迭代器
语法:
pair <iterator,iterator>equal_range(const key_type &key);//key是用于排序的关键字
Set<int> ctr;
例如:
pair<set<int>::iterator,set<int>::iterarot>p;
for(i=0;i<=5;i++) ctr.insert(i);
p=ctr.equal_range(2);
那么*p.first==2;*p.second==3;
erase()
删除集合中的元素
语法:
iterator erase(iterator i);//删除i位置元素
iterator erase(iterator start, iterator end);//删除从start开始到end(end为第一个不被删除的值)结束的元素
size_type erase(const key_type &key);//删除等于key值的所有元素(返回被删除的元素的个数)
//前两个返回第一个不被删除的双向定位器,不存在返回末尾
//第三个返回删除个数
find()
返回一个指向被查找到元素的迭代器
语法:
iterator find(const key_type &key);//查找等于key值的元素,并返回指向该元素的迭代器;
//如果没有找到,返回指向集合最后一个元素的迭代器
get_allocator()
返回集合的分配器insert()
在集合中插入元素
语法:
iterator insert(iterator i, const TYPE &val);//在迭代器i前插入val
void insert(input_iterator start, input_iterator end);//将迭代器start开始到end(end不被插入)结束返回内的元素插入到集合中
pair insert(const TYPE &val);//插入val元素,返回指向该元素的迭代器和一个布尔值来说明val是否成功被插入
//应该注意的是在集合(Sets中不能插入两个相同的元素)
lower_bound()
返回指向大于(或等于)某值的第一个元素的迭代器
语法:
iterator lower_bound(const key_type &key);//返回一个指向大于或者等于key值的第一个元素的迭代器
key_comp()
返回一个用于元素间值比较的函数
语法:
key_compare key_comp();//返回一个用于元素间值比较的函数对象
max_size()
返回集合能容纳的元素的最大限值rbegin()
返回指向集合中最后一个元素的反向迭代器
示例:
Set<int> ctr;
Set<int>::reverse_iterator rcp;
for(rcp=ctr.rbegin();rcp!=ctr.rend();rcp++)
cout<<*rcp<<” ”;
rend()
返回指向集合中第一个元素的反向迭代器size()
集合中元素的数目swap()
交换两个集合变量
语法:
void swap(set &object);//交换当前集合和object集合中的元素
upper_bound()
返回大于某个值元素的迭代器
语法:
iterator upwer_bound(const key_type &key);//返回一个指向大于key值的第一个元素的迭代器
value_comp()
返回一个用于比较元素间的值的函数
语法:
iterator upper_bound(const key_type &key);//返回一个用于比较元素间的值的函数对象
Maps & MultiMaps
C++ Maps是一种关联式容器,包含“关键字/值”对
C++ Multimaps和maps很相似,但是MultiMaps允许重复的元素
begin()
返回指向map头部的迭代器clear()
删除所有元素count()
返回指定元素出现的次数
语法:
size_type count(const KEY_TYPE &key);//返回map中键值等于key的元素的个数
empty()
如果map为空则返回trueend()
返回指向map末尾的迭代器equal_range()
返回特殊条目的迭代器对
语法:
pair equal_range(const KEY_TYPE &key);//返回两个迭代器,指向第一个键值为key的元素和指向最后一个键值为key的元素
erase()
删除一个元素
语法:
void erase(iterator i);//删除i元素
void erase(iterator start, iterator end);//删除从start开始到end(不包括end)结束的元素
size_type erase( const key_type &key );//删除等于key值的所有元素(返回被删除的元素的个数)
find()
查找一个元素
语法:
iterator find(const key_type &key);//查找等于key值的元素,并返回指向该元素的迭代器;
//如果没有找到,返回指向集合最后一个元素的迭代器.
get_allocator()
返回map的配置器insert()
插入元素
语法:
iterator insert(iterator pos, const pair<KEY_TYPE,VALUE_TYPE> &val);//插入val到pos的后面,然后返回一个指向这个元素的迭代器
void insert(input_iterator start, input_iterator end);//插入start到end的元素到map中
pair<iterator, bool> insert(const pair<KEY_TYPE,VALUE_TYPE> &val);//只有在val不存在时插入val。返回指向被插入元素的迭代器和描述是否插入的bool值
key_comp()
返回比较元素key的函数
语法:
key_compare key_comp();//返回一个用于元素间值比较的函数对象
lower_bound()
返回键值>=给定元素的第一个位置
语法:
iterator lower_bound(const key_type &key);//返回一个指向大于或者等于key值的第一个元素的迭代器
max_size()
返回可以容纳的最大元素个数rbegin()
返回一个指向map尾部的逆向迭代器rend()
返回一个指向map头部的逆向迭代器size()
返回map中元素的个数swap()
交换两个map
语法:
void swap(map &obj);//swap()交换obj和现map中的元素
upper_bound()
返回键值>给定元素的第一个位置
语法:
iterator upwer_bound(const key_type &key);//返回一个指向大于key值的第一个元素的迭代器
value_comp()
返回比较元素value的函数
语法:
value_compare value_comp();//返回一个用于比较元素value的函数
容器适配器
特点
STL中包含三种适配器:栈stack、队列queue和优先级priority_queue。适配器是容器的接口,它本身不能直接保存元素,它保存元素的机制是调用另一种顺序容器去实现,即可以把适配器看作“它保存一个容器,这个容器再保存所有元素”
STL中提供的三种适配器可以由某一种顺序容器去实现。默认下stack和queue基于deque容器实现,priority_queue则基于vector容器实现。当然在创建一个适配器时也可以指定具体的实现容器,创建适配器时在第二个参数上指定具体的顺序容器可以覆盖适配器的默认实现
由于适配器的特点,一个适配器不是可以由任一个顺序容器都可以实现的
栈stack的特点是后进先出,所以它关联的基本容器可以是任意一种顺序容器,因为这些容器类型结构都可以提供栈的操作有求,它们都提供了push_back、pop_back和back操作
队列queue的特点是先进先出,适配器要求其关联的基础容器必须提供pop_front操作,因此其不能建立在vector容器上
Stacks(堆栈)
C++队列是一种容器适配器,它给予程序员一种先进先出(FIFO)的数据结构
back()
返回一个引用,指向最后一个元素empty()
如果队列空则返回真front()
返回第一个元素pop()
删除第一个元素push()
在末尾加入一个元素size()
返回队列中元素的个数
Queues(队列)
C++队列是一种容器适配器,它给予程序员一种先进先出(FIFO)的数据结构
back()
返回一个引用,指向最后一个元素empty()
如果队列空则返回真front()
返回第一个元素pop()
删除第一个元素push()
在末尾加入一个元素size()
返回队列中元素的个数
Priority Queues(优先队列)
C++优先队列类似队列,但是在这个数据结构中的元素按照一定的断言排列有序
empty()
如果优先队列为空,则返回真pop()
删除第一个元素push()
加入一个元素size()
返回优先队列中拥有的元素的个数top()
返回优先队列中有最高优先级的元素
迭代器
解释
迭代器是一种对象,它能够用来遍历STL容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址。迭代器修改了常规指针的接口,所谓迭代器是一种概念上的抽象:那些行为上象迭代器的东西都可以叫做迭代器。然而迭代器有很多不同的能力,它可以把抽象容器和通用算法有机的统一起来
迭代器提供一些基本操作符:*
、++
、==
、!=
、=
。这些操作和C/C++“操作array元素”时的指针接口一致。不同之处在于,迭代器是个所谓的smart pointers,具有遍历复杂数据结构的能力。其下层运行机制取决于其所遍历的数据结构。因此,每一种容器型别都必须提供自己的迭代器。事实上每一种容器都将其迭代器以嵌套的方式定义于内部。因此各种迭代器的接口相同,型别却不同。这直接导出了泛型程序设计的概念:所有操作行为都使用相同接口,虽然它们的型别不同
功能特点
迭代器使开发人员不必整个实现类接口。只需提供一个迭代器,即可遍历类中的数据结构,可被用来访问一个容器类的所包函的全部元素,其行为像一个指针,但是只可被进行增加(++
)或减少(--
)操作。举一个例子,你可用一个迭代器来实现对vector容器中所含元素的遍历。
如下代码对vector容器对象生成和使用了迭代器:
vector<int> the_vector;
vector<int>::iterator the_iterator;
for(int i=0; i < 10; i++)
the_vector.push_back(i);
int total = 0;
the_iterator = the_vector.begin();
while(the_iterator != the_vector.end())
{
total += *the_iterator;
the_iterator++;
}
cout << "Total=" << total << endl;
提示:通过对一个迭代器的解引用操作(*
),可以访问到容器所包含的元素
STL常用算法
#include <algorithm>
算法 | 常用版本 | 描述 | 返回Type |
---|---|---|---|
std::find() |
find(_InIt _Fisrt,_InIt _Last,_Ty& _Val); |
从两个迭代器指定的范围中查找指定值 | 引用被查找的值的iterator或end() |
std::find_if() |
find_if(_InIt _Fisrt,_InIt _Last, _CallBack); |
从两个迭代器指定的范围中查找与回调谓词匹配的实例 | 与谓词匹配的实例的iterator或end() |
std::find_if_not() |
find_if_not(_InIt _Fisrt,_InIt _Last,_Func _CallBack); |
从迭代器范围中返回第一个不符合谓词的元素 | 第一个不符合谓词的元素的iterator或end() |
std::count() |
count(_InIt _First,_InIt _Last,_Ty& _Val); |
求得一个元素序列中与第三个参数相符的元素的个数 | 与第三个参数匹配的元素的int个数 |
std::count_if() |
count_if(_InIt _First,_InIt _Last, _CallBack); |
求得一个序列中与谓词匹配的元素的个数 | 符合条件元素的int个数 |
std::generate() |
generate(_FwdIt _First,_FwdIt _Last, _CallBack); |
通过特定值填充一个迭代器范围 | void |
std::max() |
max(_Left,_Right /*,Predicate*/); |
通过operator<或用户提供的二元谓词比较任意类型的两个元素 | 返回较大的一个元素的const引用 |
std::min() |
min(_Left,_Right /*,Predicate*/); |
通过operator<或用户提供的二元谓词比较任意类型的两个元素 | 较小的一个元素的const引用 |
std::max_element() |
max_element(_FwdIt _First,_FwdIt _Last /*,_Pred*/); |
从一组任意类型的元素元素序列中查找"最大"的一个 | 引用"最大”的元素的iterator |
std::min_element() |
min_element(_FwdIt _First,_FwdIt _Last /*,_Pred*/); |
从一组任意类型的元素元素序列中查找"最小"的一个 | 引用"最小"的元素的iterator |
adjacent_find() |
adjacent_find(_FwdIt _First, _FwdIt _Last/*,_Pred*/); |
从一组任意类型的元素序列中查找有重复的元素 | 引用重复的第一个元素的iterator或者end() |
std::all_of() |
all_of(_InIt _First,_InIt _Last,Pr _Pred); |
当一组元素序列全部与谓词匹配时返回true否则返回false | bool |
std::any_of() |
any_of(_InIt _First,_InIt _Last,_Pr _Pred); |
当一组元素序列中任意一个元素与谓词匹配时返回true否则返回false | bool |
std::none_of() |
none_of(_InIt _First,_InIt _Last,_Pr _Pred); |
当一组元素序列全部都不与谓词匹配时返回true否则返回false | bool |
std::for_each() |
for_each(_InIt _First,_InIt _Last,_CallBack); |
对指定范围内的所有元素执行一次_CallBack | _CallBackl类型 |
std::transform() |
transform(_InIt_SrcFirst,_InIt _SrcLast,_OutIt_DestBegin,_CallBack); |
对指定范围的元素执行回调后生成新的元素,然后将这些新元素保存在第三个参数指定的目标范围中 | 引用Dest范围的past-the-end的_OutputIterator |
- |
transform(_InIt _First1,_InIt _Last,_InIt _First2,_OutIt _DestBegin,_CallBack); |
对两个指定序列的元素调用二元谓词,并将结果存入到第四个参数指定的容器中 | 引用Dest范围的past-the-end的_OutputIterator |
std::equal() |
equal(_InIt _First1,_InIt _Last1,_InIt _First2 /*,_Pred*/); |
对两个不同类型的容器比较对应位置的值,当全部相等或者全部符合谓词时返回true否则返回false | bool |
std::copy() |
copy(_InIt _SrcBegin,_InIt _SrcEnd,_OutIt _DestBegin); |
将一个序列的元素复制到另一个序列中,Src范围与Dest范围不能相同,但可以重叠,std::copy不会向目标序列中插入元素,而会直接修改元素,使用前必须配合_Dest序列的resize()函数给Dest序列重分配足够的空间 | 引用Dest范围的past_the_end的_OutputIterator |
std::copy_backward() |
copy_backward(_InIt _SrcBegin,_InIt _SrcEnd,_OutIt _DestEnd); |
将Src范围的元素反向复制到Dest范围中,也就是从Src范围最后一个元素开始复制,将这个元素放在Dest范围的最后一个位置,然后再每一次复制后反向移动.第三个参数应该是_DestEnd而不是_DestBegin | 引用Dest范围的_Begin()的_OutputIterator |
std::copy_if |
copy_if(_InIt _SrcBegin,_InIt _SrcEnd,_OutIt _DestBegin,_Pr _Pred); |
对一个序列中每个准备复制的元素执行一次_Callback,如果返回值为true,那么执行copy操作,否则不执行;返回了Dest范围中最后一个复制的元素的后一个位置,这是为了配合past_the_end来删除多余的元素:复制完成后使用_Dest.erase(_CopyEndIt,past_the_end);来删除Dest范围多余的元素位置 | 返回引用Dest范围的最后一个复制的元素的后一个位置的_OutputIterator |
std::copy_n() |
copy_n(_InIt _SrcBegin,_Ty _Cnt,_OutIt _DestBegin); |
从Src范围复制_Cnt个元素到Dest范围,第二个参数是一个指定要复制的元素个数的整数 | 返回引用Dest范围的past_the_end |
std::partition_copy() |
partition_copy(_InIt _SrcBegin,_InIt _SrcEnd,_OutIt _Dest1,_OutIt _Dest2,_Pr _Pred); |
对一个序列的元素进行依据谓词返回的结果进行划分复制,首先对Src序列中的每一个元素执行一次谓词,如果返回true,那么将这个元素复制到_Dest1,如果返回false,复制到_Dest2,复制之前需要使用resize()重置Dest的空间;算法返回一个打包_Dest1和_Dest2的one_past_the_last_copied的std::pair,利用这个pair可以删除多分配的空间 | 打包引用_Dest1和_Dest2的one_past_the_last_copied的_OutputIterator的std::pair |
std::move() |
move(_InIt _SrcBegin,_InIt _SrcEnd,_OutIt _DestBegin); |
需要给元素提供移动赋值运算符,将Src序列的元素通过移动赋值运算符移动到Dest序列,在移动操作中,SrcObject被重置了,因为DstObject接管了SrcObject资源的所有权,这意味着在move操作过后Src序列中的对象不能再使用 | 返回Dest范围的引用past_the_end的_OutputIterator |
std::move_backward() |
move_backward(_InIt _SrcBegin,_InIt _SrcEnd,_OutIt _DstEnd) |
使用了和std::move()相同的移动机制,但是按照从最后一个元素向第一个元素的顺序进行移动 | 返回Dest范围的引用_Begin()的_OutputIterator |
std::replace() |
replace(_FwdIt _First,_FwdIt _Last,const _Ty& _OldVal,const _Ty& _NewVal); |
这个算法将一个范围中的匹配某个值的元素替换为第三个参数指定的新值 | void |
std::replace_if() |
replace_if(_FwdIt _First,_FwdIt _Last,_Pr _Pred,const _Ty& _NewVal); |
这个算法将一个范围中的匹配某个谓词的元素替换为第三个参数指定的新值 | void |
std::remove() |
remove(_FwdIt _First,_FwdIt _Last,const _Ty& _Val); |
这个算法并不是将序列中与_Val匹配的元素直接删除,而是将它们移动到容器的末端,然后返回引用第一个被移除的元素的iterator,可以利用这个iterator和end()将被移除的元素彻底擦除 | 返回引用第一个被移除的元素的_FwdIterator |
std::remove_if() |
remove_if(_FwdIt _First,_FwdIt _Last,_Pr _Pred); |
这个算法并不是将序列中与谓词匹配的元素直接删除,而是将它们移动到容器的末端,然后返回引用第一个被移除的元素的iterator,可以利用这个iterator和end()将被移除的元素彻底擦除 | 返回引用第一个被移除的元素的_FwdIterator |
std::unique() |
unique(_FwdIt _First,_FwdIt _Last /*,_Pr _Pred)*/; |
std::unique算法是特殊的std::remove算法,和后者一样,std::unique并不是直接将重复的元素删除,而是将它们全部移动到容器的尾端,然后返回引用第一个被移除的元素的iterator,可以利用这个iterator和end()将被移除的元素彻底擦除 | 返回引用第一个被移除的元素的_FwdIterator |
std::unique_copy |
unique(_FwdIt _SrcBegin,_FwdIt _SrcEnd,_OutIt _DestBegin /*,_Pr _Pred*/); |
std::unique()的基本形式是就地操作数据,std::unique_copy则是将操作的结果复制到Dest范围中 | 返回引用Dest范围的元素的_OutputIterator |
std::reverse() |
reverse(_BidIt _First,_BidIt _Last); |
将范围中的第一个元素和最后一个元素交换,第二个元素和倒数第二个元素交换,依此类推 | Void |
std::reverse_copy() |
reverse_copy(_BidIt _SrcBegin,_BidIt _SrcEnd,_OutIt _DestBegin); |
std::reverse是就地操作数据,std::reverse_copy将结果复制到Dest范围中 | 返回引用Dest范围的元素的_OutputIterator |
std::sort() |
sort(_RanIt _First,_RanIt _Last /*,_Pr _Pred*/); |
将范围中的元素按operator<或_CallBack进行排序 | Void |
std::merge() |
merge(_InIt _SrcBegin1,_InIt _SrcEnd1,_InIt _SrcBegin2,_InIt _SrcEnd2,_OutIt _DestBegin,/*,_Pr _Prd*/); |
将两个排好序的Src序列合并成一个元素序列,然后将结果复制到Dest序列中,并且依然保持排序的顺序,结果是一个包含两个Src序列的所有元素的有序序列,注意一定要使用两个排好序的序列进行merge操作 | 引用Dest序列的past_the_end的_OutputIterator |
std::is_sorted() |
sort(_FwdIt _First,_FwdIt _Last /*,_Pr _Pred*/); |
验证一个序列是否是有序序列.如果是,返回true,否则返回false | bool |
std:random_shuffle() |
random_shuffle(_RanIt _First,_RanIt _Last /*,_Fn& _Func*/) |
将一个序列的顺序打乱,这个算法适用于洗牌之类的任务,对一个版本默认使用标准C库的rand()函数,第二个版本需要提供一个随机数生成器,以适应不同问题领域的随机性 | void |
集合算法
算法 | 常用版本 | 描述 | 返回Type |
---|---|---|---|
std::includes() |
includes(_InIt _First1,_InIt _Last1,_InIt _First2,_InIt _Last2 /*,_Pr _Pred*/); |
验证第二个序列是否是第一个序列的子集,注意不是真子集,而是子集,如果是返回true,否则返回false | bool |
std::set_union() |
set_union(_InIt _SrcBegin1, _InIt _SrcEnd1, _InIt _SrcBegin2, _InIt _SrcEnd2, _OutIt _DestBegin /*,_Pr _Pred*/); |
计算两个有序序列的并集,然后将并集的结果存入第四个参数指定的Dest序列中,注意在计算前必须给Dest容器分配足够的空间,因为Dest范围最大是_Src1和_Src2的size()和,所以在进行合并后有可能会留下一些空间,set_union算法返回一个引用Dest范围中最后一个被添加进去的元素的后一个位置的iterator,利用它可以将Dest中多余的空间删除 | 返回一个引用Dest范围中最后一个被添加进去的元素的后一个位置的_OutputIterator |
std::set_intersection() |
set_intersection(_InIt _SrcBegin1, _InIt _SrcEnd1, _InIt _SrcBegin2, _InIt _SrcEnd2, _OutIt _DestBegin /*,_Pr _Pred*/); |
计算两个有序序列的交集,然后将交集的结果存入第四个参数指定的Dest序列中,注意在计算前必须给Dest容器分配足够的空间,因为Dest范围最大是两个_Src范围的size的最大值,所以在进行取交集后有可能会留下一些空间,set_union算法返回一个引用Dest范围中最后一个被添加进去的元素的后一个位置的iterator,利用它可以将Dest中多余的空间删除 | 返回一个引用Dest范围中最后一个被添加进去的元素的后一个位置的_OutputIterator |
std ::set_difference() |
set_difference(_InIt _SrcBegin1, _InIt _SrcEnd1, _InIt _SrcBegin2, _InIt _SrcEnd2, _OutIt _DestBegin /*,_Pr _Pred*/); |
计算两个有序序列的集合差,(集合差:所有存在于第一个集合,但是不存在与第二个集合中的所有元素),然后将求集合差的结果存入第四个参数指定的Dest序列中,注意在计算前必须给Dest容器分配足够的空间,因为Dest范围最大是两个_Src范围的size的最大值,所以在进行取交集后有可能会留下一些空间,set_union算法返回一个引用Dest范围中最后一个被添加进去的元素的后一个位置的iterator,利用它可以将Dest中多余的空间删除 | 返回一个引用Dest范围中最后一个被添加进去的元素的后一个位置的_OutputIterator |
std::set_symmetric_difference() |
set_symmetric_difference(_InIt _SrcBegin1, _InIt _SrcEnd1, _InIt _SrcBegin2, _InIt _SrcEnd2, _OutIt _DestBegin /*,_Pr _Pred*/); |
计算两个有序序列的对称集合差,(对称集合差:所有存在于某一个集合,但是不存在与第二个集合中的元素),然后将求对称集合差的结果存入第四个参数指定的Dest序列中,注意在计算前必须给Dest容器分配足够的空间,因为Dest范围最大是_Src1和_Src2的size()和,所以在进行取交集后有可能会留下一些空间,set_union算法返回一个引用Dest范围中最后一个被添加进去的元素的后一个位置的iterator,利用它可以将Dest中多余的空间删除 | 返回一个引用Dest范围中最后一个被添加进去的元素的后一个位置的_OutputIterator |
Warning: 务必要确保Dest范围足够大,足以保存操作的结果
- 对于set_union()和set_symmetric_difference(),结果大小的上限是两个输入范围的总和
- 对于set_intersection()和set_difference(),结果大小的上限是两个输入范围大小中的最大值
#include <numeric>
算法 | 常用版本 | 描述 | 返回Type |
---|---|---|---|
std::accumulate() |
accumulate(_InIt _First,_InIt _Last,_Ty& _Val); |
对一个由两个迭代器指定的序列的元素求和 | 返回一个指定的序列的求和的值 |
- |
accumulate(_InIt _First,_InIt _Last,Ty& _Val,_Func _CallBack); |
对一个由两个迭代器指定的序列进行调用者指定的操作 | 返回对一个序列执行指定操作的值 |
std::iota() |
iota(_FwdIt _First,_FwdIt _Last,_Ty& _Val); |
生成一个指定范围内的序列值,由第三个实参指定的值开始使用operator++递增,调用此算法之前必须要指定容器的size() | void |
算法复杂度大O表示法
算法复杂度 | 大O表示法 | 说明 | 事例算法 |
---|---|---|---|
常数 | O(1) | 运行时间与输入量无关 | 访问数组中的某个元素 |
对数 | O(log n) | 运行时间是输入量以2为底的对数的函数 | 使用二分法查找有序列表中的元素 |
线性 | O(n) | 运行时间与输入量成正比 | 未排序列表中查找元素 |
线性对数 | O(n log n) | 运行时间是输入量的对数函数的线性倍的函数 | 归并排序 |
二次方 | O(n²) | 运行时间是输入量的平方的函数 | 较慢的排序算法,如选择排序算法 |
STL中的算法
STL算法部分主要由头文件<algorithm>
,<numeric>
,<functional>
组成。
要使用STL中的算法函数必须包含头文件<algorithm>
对于数值算法须包含<numeric>
,<functional>
中则定义了一些模板类,用来声明函数对象。
STL中算法大致分为四类:
- 非可变序列算法:指不直接修改其所操作的容器内容的算法。
- 可变序列算法:指可以修改它们所操作的容器内容的算法。
- 排序算法:包括对序列进行排序和合并的算法、搜索算法以及有序序列上的集合操作。
- 数值算法:对容器内容进行数值计算。
查找算法(13个):判断容器中是否包含某个值
adjacent_find
: 在iterator对标识元素范围内,查找一对相邻重复元素,找到则返回指向这对元素的第一个元素的ForwardIterator。否则返回last。重载版本使用输入的二元操作符代替相等的判断。
binary_search
: 在有序序列中查找value,找到返回true。重载的版本实用指定的比较函数对象或函数指针来判断相等。
count
: 利用等于操作符,把标志范围内的元素与输入值比较,返回相等元素个数。
count_if
: 利用输入的操作符,对标志范围内的元素进行操作,返回结果为true的个数。
equal_range
: 功能类似equal,返回一对iterator,第一个表示lower_bound,第二个表示upper_bound。
find
: 利用底层元素的等于操作符,对指定范围内的元素与输入值进行比较。当匹配时,结束搜索,返回该元素的一个InputIterator。
find_end
: 在指定范围内查找"由输入的另外一对iterator标志的第二个序列"的最后一次出现。找到则返回最后一对的第一个ForwardIterator,否则返回输入的"另外一对"的第一个ForwardIterator。重载版本使用用户输入的操作符代替等于操作。
find_first_of
: 在指定范围内查找"由输入的另外一对iterator标志的第二个序列"中任意一个元素的第一次出现。重载版本中使用了用户自定义操作符。
find_if
: 使用输入的函数代替等于操作符执行find。
lower_bound
: 返回一个ForwardIterator,指向在有序序列范围内的可以插入指定值而不破坏容器顺序的第一个位置。重载函数使用自定义比较操作。
upper_bound
: 返回一个ForwardIterator,指向在有序序列范围内插入value而不破坏容器顺序的最后一个位置,该位置标志一个大于value的值。重载函数使用自定义比较操作。
search
: 给出两个范围,返回一个ForwardIterator,查找成功指向第一个范围内第一次出现子序列(第二个范围)的位置,查找失败指向last1。重载版本使用自定义的比较操作。
search_n
: 在指定范围内查找val出现n次的子序列。重载版本使用自定义的比较操作。
排序和通用算法(14个):提供元素排序策略
inplace_merge
: 合并两个有序序列,结果序列覆盖两端范围。重载版本使用输入的操作进行排序。
merge
: 合并两个有序序列,存放到另一个序列。重载版本使用自定义的比较。
nth_element
: 将范围内的序列重新排序,使所有小于第n个元素的元素都出现在它前面,而大于它的都出现在后面。重载版本使用自定义的比较操作。
partial_sort
: 对序列做部分排序,被排序元素个数正好可以被放到范围内。重载版本使用自定义的比较操作。
partial_sort_copy
: 与partial_sort类似,不过将经过排序的序列复制到另一个容器。
partition
: 对指定范围内元素重新排序,使用输入的函数,把结果为true的元素放在结果为false的元素之前。
random_shuffle
: 对指定范围内的元素随机调整次序。重载版本输入一个随机数产生操作。
reverse
: 将指定范围内元素重新反序排序。
reverse_copy
: 与reverse类似,不过将结果写入另一个容器。
rotate
: 将指定范围内元素移到容器末尾,由middle指向的元素成为容器第一个元素。
rotate_copy
: 与rotate类似,不过将结果写入另一个容器。
sort
: 以升序重新排列指定范围内的元素。重载版本使用自定义的比较操作。
stable_sort
: 与sort类似,不过保留相等元素之间的顺序关系。
stable_partition
: 与partition类似,不过不保证保留容器中的相对顺序。
删除和替换算法(15个)
copy
: 复制序列
copy_backward
: 与copy相同,不过元素是以相反顺序被拷贝。
iter_swap
: 交换两个ForwardIterator的值。
remove
: 删除指定范围内所有等于指定元素的元素。注意,该函数不是真正删除函数。内置函数不适合使用remove和remove_if函数。
remove_copy
: 将所有不匹配元素复制到一个制定容器,返回OutputIterator指向被拷贝的末元素的下一个位置。
remove_if
: 删除指定范围内输入操作结果为true的所有元素。
remove_copy_if
: 将所有不匹配元素拷贝到一个指定容器。
replace
: 将指定范围内所有等于vold的元素都用vnew代替。
replace_copy
: 与replace类似,不过将结果写入另一个容器。
replace_if
: 将指定范围内所有操作结果为true的元素用新值代替。
replace_copy_if
: 与replace_if,不过将结果写入另一个容器。
swap
: 交换存储在两个对象中的值。
swap_range
: 将指定范围内的元素与另一个序列元素值进行交换。
unique
: 清除序列中重复元素,和remove类似,它也不能真正删除元素。重载版本使用自定义比较操作。
unique_copy
: 与unique类似,不过把结果输出到另一个容器。
排列组合算法(2个):提供计算给定集合按一定顺序的所有可能排列组合
next_permutation
: 取出当前范围内的排列,并重新排序为下一个排列。重载版本使用自定义的比较操作。
prev_permutation
: 取出指定范围内的序列并将它重新排序为上一个序列。如果不存在上一个序列则返回false。重载版本使用自定义的比较操作。
算术算法(4个)
accumulate
: iterator对标识的序列段元素之和,加到一个由val指定的初始值上。重载版本不再做加法,而是传进来的二元操作符被应用到元素上。
partial_sum
: 创建一个新序列,其中每个元素值代表指定范围内该位置前所有元素之和。重载版本使用自定义操作代替加法。
inner_product
: 对两个序列做内积(对应元素相乘,再求和)并将内积加到一个输入的初始值上。重载版本使用用户定义的操作。
adjacent_difference
: 创建一个新序列,新序列中每个新值代表当前元素与上一个元素的差。重载版本用指定二元操作计算相邻元素的差。
生成和异变算法(6个)
fill
: 将输入值赋给标志范围内的所有元素。
fill_n
: 将输入值赋给first到first+n范围内的所有元素。
for_each
: 用指定函数依次对指定范围内所有元素进行迭代访问,返回所指定的函数类型。该函数不得修改序列中的元素。
generate
: 连续调用输入的函数来填充指定的范围。
generate_n
: 与generate函数类似,填充从指定iterator开始的n个元素。
transform
: 将输入的操作作用与指定范围内的每个元素,并产生一个新的序列。重载版本将操作作用在一对元素上,另外一个元素来自输入的另外一个序列。结果输出到指定容器。
关系算法(8个)
equal
: 如果两个序列在标志范围内元素都相等,返回true。重载版本使用输入的操作符代替默认的等于操作符。
includes
: 判断第一个指定范围内的所有元素是否都被第二个范围包含,使用底层元素的<操作符,成功返回true。重载版本使用用户输入的函数。
lexicographical_compare
: 比较两个序列。重载版本使用用户自定义比较操作。
max
: 返回两个元素中较大一个。重载版本使用自定义比较操作。
max_element
: 返回一个ForwardIterator,指出序列中最大的元素。重载版本使用自定义比较操作。
min
: 返回两个元素中较小一个。重载版本使用自定义比较操作。
min_element
: 返回一个ForwardIterator,指出序列中最小的元素。重载版本使用自定义比较操作。
mismatch
: 并行比较两个序列,指出第一个不匹配的位置,返回一对iterator,标志第一个不匹配元素位置。如果都匹配,返回每个容器的last。重载版本使用自定义的比较操作。
集合算法(4个)
set_union
: 构造一个有序序列,包含两个序列中所有的不重复元素。重载版本使用自定义的比较操作。
set_intersection
: 构造一个有序序列,其中元素在两个序列中都存在。重载版本使用自定义的比较操作。
set_difference
: 构造一个有序序列,该序列仅保留第一个序列中存在的而第二个中不存在的元素。重载版本使用自定义的比较操作。
set_symmetric_difference
: 构造一个有序序列,该序列取两个序列的对称差集(并集-交集)。
堆算法(4个)
make_heap
: 把指定范围内的元素生成一个堆。重载版本使用自定义比较操作。
pop_heap
: 并不真正把最大元素从堆中弹出,而是重新排序堆。它把first和last-1交换,然后重新生成一个堆。可使用容器的back来访问被"弹出"的元素或者使用pop_back进行真正的删除。重载版本使用自定义的比较操作。
push_heap
: 假设first到last-1是一个有效堆,要被加入到堆的元素存放在位置last-1,重新生成堆。在指向该函数前,必须先把元素插入容器后。重载版本使用指定的比较操作。
sort_heap
: 对指定范围内的序列重新排序,它假设该序列是个有序堆。重载版本使用自定义比较操作。
C++学习笔记-STL的更多相关文章
- C++学习笔记——STL(标准模板库)
1.首先.需要学习C++ 模板的概念 2.C++ STL(标准模板库)是一套功能强大的 C++ 模板类,提供了通用的模板类和函数,这些模板类和函数可以实现多种流行和常用的算法和数据结构,如向量.链表. ...
- STL学习笔记---STL简介
1.概述 STL是通用类模版和算法的集合,它提供给程序员一些标准的数据结构和算法的实现.STL三大关键组成: 容器(Containers),用来管理类对象的集合 迭代器(Iterators),用来在一 ...
- VC学习笔记----STL库
STL = Standard Template Library,标准模板库,惠普实验室开发的一系列软件的统称.它是由Alexander Stepanov.Meng Lee和David R Muss ...
- Day 3 学习笔记
Day 3 学习笔记 STL 模板库 一.结构体 结构体是把你所需要的一些自定义的类型(原类型.实例(:包括函数)的集合)都放到一个变量包里. 然后这个变量包与原先的类型差不多,可以开数组,是一种数据 ...
- STL学习笔记序言
笔者作为计算机科学与技术专业的学生,学习并使用C++已经有3年了.在接触STL之前的编程习惯是,所有程序的功能包括数据结构.算法等都是亲自实现,效率极其缓慢.后来从使用STL的vector开始慢慢的感 ...
- Effective STL 学习笔记 39 ~ 41
Effective STL 学习笔记 39 ~ 41 */--> div.org-src-container { font-size: 85%; font-family: monospace; ...
- Effective STL 学习笔记 Item 38 : Design functor classes for pass-by-value
Effective STL 学习笔记 Item 38 : Design functor classes for pass-by-value */--> div.org-src-container ...
- Effective STL 学习笔记 Item 34: 了解哪些算法希望输入有序数据
Effective STL 学习笔记 Item 34: 了解哪些算法希望输入有序数据 */--> div.org-src-container { font-size: 85%; font-fam ...
- Effective STL 学习笔记 32 ~ 33
Effective STL 学习笔记 32 ~ 33 */--> div.org-src-container { font-size: 85%; font-family: monospace; ...
随机推荐
- Java8-Stream-No.07
import java.util.ArrayList; import java.util.List; import java.util.stream.IntStream; public class S ...
- [Spring] Spring Data JPA
Previouly we need to define a DAO interface and a DAO impl for 'Employee', it is not so reuseable, s ...
- Docker Gitlib创建项目后仓库连接IP地址不一致问题(包括进入docker中容器命令及退出命令)
首次在内网搭建Gitlab环境,在成功后在Gitlab上新建了一个项目. 然而在IDEA上clone项目时发现,项目地址如下: git@0096ce63c43f:root/jump.git 或者这样 ...
- 排列组合C、A
排列组合是组合学最基本的概念.所谓排列,就是指从给定个数的元素中取出指定个数的元素进行排序.组合则是指从给定个数的元素中仅仅取出指定个数的元素,不考虑排序. 排列组合定义及公式 排列的定义:从n个不同 ...
- Vue 事件监听实现导航栏吸顶效果(页面滚动后定位)
Vue 事件监听实现导航栏吸顶效果(页面滚动后定位) Howie126313 关注 2017.11.19 15:05* 字数 100 阅读 3154评论 0喜欢 0 所说的吸顶效果就是在页面没有滑动之 ...
- linux系统编程--信号
信号的概念 man 7 siganl 查看man手册 信号在我们的生活中随处可见, 如:古代战争中摔杯为号:现代战争中的信号弹:体育比赛中使用的信号枪......他们都有共性:1. 简单 2. 不能 ...
- OI程序常见的设计陷阱
宏定义的问题 有时候为了方便,我会大量使用宏定义.但是最近我发现下面这两个宏定义老是出问题: #define SET(x,a) memset(x,a,sizeof(x)) inline void wo ...
- 【Redis 向Redis中批量导入mysql中的数据(亲自测试)】
转自:https://blog.csdn.net/kenianni/article/details/84910638 有改动,仅供个人学习 问题提出:缓存的冷启动问题 应用系统新版本上线,这时候 re ...
- django快速实现完整登录系统,把登陆注册串在一起并增加cookie(六)
1.使用之前创建的项目和应用 mysite3 account 2.使用之前的数据库构造 class User(models.Model): username=models.CharField(max ...
- volatile写读的内存语义
1,当写一个volatile变量时,JMM(java内存模型)会把该线程本地内存中的所有共享变量刷新到主内存中去 2,当读取一个volatile变量时,该线程会将本地内存置为无效,线程将从主内存中读取 ...