1、STL 参考资料袁辉勇 整理2009 年 11 月STL 资料 2009 年1/43目录STL 介绍 31、STL 简介 32、算法 33、容器 34、迭代器 45、使用注意 4一、stack 堆栈 5成员函数: 5实例程序: 5二、queue 队列 6成员函数: 6实例程序: 6三、Priority Queues 优先队列 .7成员函数: 7实例程序: 7四、Bitset 位集合 9成员函数: 9实例程序: 9五、list 列表 .11成员函数: 11实例程序: 12六、vector 向量 .13成员函数: 13实例程序: 14七、map / multimap 映射与多重映射 .15map
2、成员函数: 15Map 实例程序: 17MultiMap 实例程序: .18八、set / multiset 集合与多重集合 .19成员函数: 19Set 实例程序: 20MultiSet 实例程序: .21九、deque (Double Ended Queue) 双端队列 22成员函数: 22实例程序: 23十、string 字符串 .24成员函数: 24实例程序: 28十一、常用算法调用 291. for_each292. min_element / max_element 293. copy / copy_n /copy_backward294. fill / fill_n .29STL
3、 资料 2009 年2/435. remove / remove_if 306. unique .317. rotate.328. random_shuffle.329. partition / stable_partition 3310. sort / stable_sort .3311. partial_sort3412. nth_element 3413. lower_bound / upper_bound /要求区间有序 .3414. binary_search /要求有序区间 3515. merge / inplace_merge .3516. includes.3617. set_
4、union, set_intersection, set_difference, set_symmetric_diffrece.3618. next_permutation / prev_permutation 3619. power3720. heap operations.3821. min / max / swap 3922. numeric_limits39STL 资料 2009 年3/43STL 介绍1、STL 简介STL(Standard Template Library,标准模板库)是惠普实验室开发的一系列软件的统称。它是由 Alexander Stepanov、Meng Lee
5、 和 David R Musser 在惠普实验室工作时所开发出来的。现在虽说它主要出现在 C+中,但在被引入 C+之前该技术就已经存在了很长的一段时间。STL 的代码从广义上讲分为三类:algorithm(算法) 、container (容器)和iterator(迭代器) ,几乎所有的代码都采用了模板类和模版函数的方式,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会。在 C+标准中,STL 被组织为下面的13 个头文件:、 、和 。以下笔者就简单介绍一下 STL 各个部分的主要特点。2、算法大家都能取得的一个共识是函数库对数据类型的选择对其可重用性起着至关重要的作用。举例来说,一
6、个求方根的函数,在使用浮点数作为其参数类型的情况下的可重用性肯定比使用整型作为它的参数类性要高。而 C+通过模板的机制允许推迟对某些类型的选择,直到真正想使用模板或者说对模板进行特化的时候,STL 就利用了这一点提供了相当多的有用算法。它是在一个有效的框架中完成这些算法的 你可以将所有的类型划分为少数的几类,然后就可以在模版的参数中使用一种类型替换掉同一种类中的其他类型。STL 提供了大约 100 个实现算法的模版函数,比如算法 for_each 将为指定序列中的每一个元素调用指定的函数,stable_sort 以你所指定的规则对序列进行稳定性排序等等。这样一来,只要我们熟悉了 STL 之后,
7、许多代码可以被大大的化简,只需要通过调用一两个算法模板,就可以完成所需要的功能并大大地提升效率。算法部分主要由头文件,和 组成。是所有 STL 头文件中最大的一个(尽管它很好理解) ,它是由一大堆模版函数组成的,可以认为每个函数在很大程度上都是独立的,其中常用到的功能范围涉及到比较、交换、查找、遍历操作、复制、修改、移除、反转、排序、合并等等。 体积很小,只包括几个在序列上面进行简单数学运算的模板函数,包括加法和乘法在序列上的一些操作。中则定义了一些模板类,用以声明函数对象。3、容器在实际的开发过程中,数据结构本身的重要性不会逊于操作于数据结构的算法的重要性,当程序中存在着对时间要求很高的部分
8、时,数据结构的选择就显得更加重要。经典的数据结构数量有限,但是我们常常重复着一些为了实现向量、链表等结构而编写的代码,这些代码都十分相似,只是为了适应不同数据的变化而在细节上有所出入。STL 容器就为我们提供了这样的方便,它允许我们重复利用已有的实现构造自己的特定类型下的数据结构,通过设置一些模板类,STL 容器对最常用的数据结构提供了支持,这些模板的参数允许我们指定容器中元素的数据类型,可以将我们许多重复而乏味的工作简化。容器部分主要由头文件,和组成。对于常用的一些容器和容器适配器(可以看作由其它容器实现的容器) ,可以STL 资料 2009 年4/43通过下表总结一下它们和相应头文件的对应
9、关系。数据结构 描述 实现头文件向量(vector) 连续存储的元素 列表(list) 由节点组成的双向链表,每个结点包含着一个元素 双队列(deque) 连续存储的指向不同元素的指针所组成的数组 集合(set)由节点组成的红黑树,每个节点都包含着一个元素,节点之间以某种作用于元素对的谓词排列,没有两个不同的元素能够拥有相同的次序多重集合(multiset) 允许存在两个次序相等的元素的集合 栈(stack) 后进先出的值的排列 队列(queue) 先进先出的执的排列 优先队列(priority_queue)元素的次序是由作用于所存储的值对上的某种谓词决定的的一种队列 映射(map) 由键,值
10、对组成的集合,以某种作用于键对上的谓词排列 多重映射(multimap) 允许键对有相等的次序的映射 4、迭代器下面要说的迭代器从作用上来说是最基本的部分,可是理解起来比前两者都要费力一些(至少笔者是这样) 。软件设计有一个基本原则,所有的问题都可以通过引进一个间接层来简化,这种简化在 STL 中就是用迭代器来完成的。概括来说,迭代器在 STL 中用来将算法和容器联系起来,起着一种黏和剂的作用。几乎 STL 提供的所有算法都是通过迭代器存取元素序列进行工作的,每一个容器都定义了其本身所专有的迭代器,用以存取容器中的元素。迭代器部分主要由头文件,和组成。是一个很小的头文件,它包括了贯穿使用在 S
11、TL 中的几个模板的声明, 中提供了迭代器使用的许多方法,而对于的描述则十分的困难,它以不同寻常的方式为容器中的元素分配存储空间,同时也为某些算法执行期间产生的临时对象提供机制, 中的主要部分是模板类 allocator,它负责产生所有容器中的默认分配器。5、使用注意STL 的区间都是左闭右开的。例如: start, end) 表示从 start 开始到 end 之前一个位置。STL 资料 2009 年5/43一、stack 堆栈头文件: #include实例化: stackStackName成员函数:bool empty(); 栈为空返回 true 否则返回 false.void pop()
12、; 移除堆栈中最顶层元素。void push( const TYPE 将 val 值压栈,使其成为栈顶的第一个元素size_type size(); 返当前堆栈中的元素数目TYPE 返回对栈顶元素的引用实例程序:#include #include #include using namespace std;int main() stacks;s.push(1); s.push(2); s.push(3);cout 实例化: queueQueueName 成员函数:bool empty(); 队列为空返回 true 否则返回 false.void pop(); 删除队列的一个元素。void pus
13、h( const TYPE 将 val 元素加入队列。size_type size(); 返当前队列中的元素数目TYPE 返回一个引用,指向队列的最后一个元素。TYPE 返回队列第一个元素的引用。实例程序:#include #include #include using namespace std;int main() queues;s.push(100); s.push(200); s.push(300);cout )进行部分排序,使得每次出栈的元素都是最小(优先级最高的) 元素。可以使用其他的比较方式。头文件: #include实例化: priority_queuePriorityQueu
14、eName成员函数:bool empty(); 优先队列为空返回 true 否则返回 false.void pop(); 删除优先队列中的第一个元素。void push( const TYPE 添加一个元素到优先队列中,值为 val。size_type size(); 返当前队列中的元素数目TYPE 返回一个引用,指向最高优先级的元素。默认的比较方式是使用小于号运算符( minIntQ; /注意 v 下面的空格:vpriority_queue, greater maxFloatQ;struct node int i;bool operator minNodeQ;以上三个优先队列出队的元素分别是
15、最小的整数、最大的浮点数、成员 i 最小的 node。实例程序:#include #include #include using namespace std;#define pow2(a) (a)*(a)#define dist2(x, y) (pow2(x) + pow2(y)struct coord int x, y;const bool operator s; coord a;a.x = 3, a.y = 2;s.push(a);a.x = 1, a.y = 2;s.push(a);a.x = 2, a.y = 2;s.push(a);cout 实例化: bitsetbs; /容纳 bi
16、ts 位,不设置初值( 全零) bitsetbs(unsigned long /用 unsigned long 初始化bitsetbs(const string /用 string 来初始化成员函数:构造函数:bitset();bitset( unsigned long val );以无参的形式创建 bitset,或把一个长无符号整数转为二进制插入到 bitset 中。模板中提供的数字决定 bitset 有多长。操作符!=, =, 如果有位被置 1 返回 true,否则返回falsesize_type count(); 返回被设置成 1 的位的个数。bitset bitset 反转 bitse
17、t 中所有的位反转 pos 上的位(pos 是 unsigned long)bool none(); 如果没有位被置 1 返回 true,否则 falsebitset bitset 置零 bitset 中所有的位置零 pos 上的位(pos 是 unsigned long)bitset bitset 置 1 bitset 中所有的位置 1 pos 上的位(pos 是 unsigned long)bool test( size_t pos ); 如果指定位为 1 返回 true,否则 falsestring to_string(); 转换成 string 返回以便输出,可直接coutunsign
18、ed long to_ulong(); 转换成 unsigned long 返回.操作符的使用:bitset:reference bitset:operator (size_t idx)bool bitset:operator (size_t idx) const第一种形式返回的是对在 idx 位置的那个位的引用,所以可以把它当作左值进行修改。第二种类型返回的是 bool 类型,输出前需要进行强制类型转换。istreamint main()bitset bs;bs = 1;cout = 1;cout 实例化: listListName成员函数:构造函数(使得可以在定义时赋初值)list ();
19、list (size_type n, const TYPE void assign(size_type num, const TYPE 清空链表,插入区间start, end)的内容到 list 中清空链表,插入 num 个值为 val 的元素TYPE iterator erase(iterator start, iterator end);删除 pos 所指元素并返回下一元素迭代器删除start, end)之间的元素,并返回最后一个被删除元素的下个元素的迭代器iterator insert( iterator pos, const TYPE void insert( iterator pos
20、, size_type num, const TYPE void insert( iterator pos, input_iterator start, input_iterator end );插入一个值为 value 的元素在 pos 位置并返回其迭代器,原 pos 及以后的元素后移。插入 num 个值为 value 的元素在 pos 位置,原 pos 及以后元素后移。插入start, end)之间的元素到 pos 位置,原 pos 及以后元素后移void merge(list void merge(list 删除链表的最后一个元素。void pop_front(); 删除链表的第一个元素
21、。void push_back( const TYPE 将 val 连接到链表的最后。void push_front( const TYPE 将 val 连接到链表的头部。STL 资料 2009 年12/43void remove( const TYPE 删除链表中所有值为 val 的元素。void remove_if(bool testfunc)/ bool testfunc(TYPE int main() listlis;list:iterator li;for (int i = 0; i 实例化: vectorVectorName 成员函数:构造函数(使得可以在定义时赋初值)vector
22、();vector(size_type n, const TYPE void assign(size_type num, const TYPE 清空 vector,插入区间start, end)的内容到 list 中清空 vector,插入 num 个值为 val 的元素TYPE at(size_type loc) 返回在 loc 位置元素的值的引用,有左值TYPE iterator erase(iterator start, iterator end);删除 loc 所指元素并返回下一元素迭代器删除start, end)之间的元素,并返回最后一个被删除元素的下个元素的迭代器iterator
23、insert( iterator loc, const TYPE void insert( iterator loc, size_type num, const TYPE void insert( iterator loc, input_iterator start, input_iterator end );插入一个值为 value 的元素在 loc 位置并返回其迭代器,原 loc 及以后的元素后移。插入 num 个值为 value 的元素在 loc 位置,原 loc 及以后元素后移。插入start, end)之间的元素到 loc 位置,原 loc 及以后元素后移void pop_back(
24、); 删除 vector 的最后一个元素。void push_back( const TYPE 将 val 放置到 vector 的最后。void reserve(size_type size) 预留至少共容纳 size 个元素的空间size_type size() 返回 list 中元素的数量。void resize( size_type n,TYPE val = 0)将 vector 大小重置为 n, 若 n (vt).swap(vt); /回收 vt 中多余元素占用的空间vector().swap(vt); /回收 vt 占用的所有空间也就是创建一个匿名的空的 vector类型变量(前一
25、句还执行了用 vt 对其初始化)并与 vt 交换,然后这个变量在这条语句结束时被自动释放。实例程序:#include #include #include using namespace std;int main() vector a;for (int i = 0; i 原型:namespace std template ,class Allocator = allocator class map;template ,class Allocator = allocator class multimap;这里解释一下“关键字/值”对: 在 std 里面定义的一个结构体,有 first 和secon
26、d 两个不同类型的成员,原型如下:namespace stdtemplate ;struct pairT1 first;T2 second; /other functions由于 pair 是个结构体,而 map/multimap 里面存放的是 pair, 所以对于这两个容器中的元素,需要使用 element.first 和 element.second 来访问其中的值。在插入的时候可以使用 pair(key, value)产生一个临时变量来插入,或者使用 make_pair(key, value)来产生,但是要严格注意 key 和 value 的类型,比如 make_pair(1, 0)是不
27、等于 make_pair(1, 0.0)的。实例化(map) : mapMapName; 实例化(multimap) : multimapMultiMapName;map 成员函数:构造函数(使得可以在定义时赋初值)map();map(const map (上面的 insert 对 multimap 无返回值)iterator insert( iterator loc, pair void insert(input_iterator start, input_iterator end );插入一个 pair 类型的元素 , 对 map 返回一个 pair,其 first 是指向插入元素的迭代器
28、,second 表示是否插入成功从 loc 开始寻找一个可以插入值为value 的元素的位置将其插入并返回其迭代器插入start, end)之间的元素到容器中void erase(iterator loc)void erase(iterator start, iterator end)size_type erase(const key_type 返回一个迭代器,指向键值 = key 的第一个元素。iterator upper_bound( const key_type 返回一个迭代器,指向键值 key 的第一个元素。size_type size() 返回元素的数量。void swap( map
29、 交换两个 map 中的元素key_compare key_comp(); 返回一个比较 key 的函数。value_compare value _comp(); 返回一个比较 value 的函数。reverse_iterator rbegin(); 返回一个逆向迭代器,指向链表的末尾reverse_iterator rend(); 返回一个指向开头之前位置的逆向迭代器默认的比较方式是使用小于号运算符( minIntMap; /注意 v 下面的空格:vmap maxFloatMap;struct nodeint i;bool operator minNodeMap;STL 资料 2009 年1
30、8/43以上三个 map/multimap 的元素分别按照整数升序、浮点降序、node.i 升序排列的。Map 实例程序:#include #include #include using namespace std;struct T1 int v;bool operatormt1; /example for user-defined classmapmt2; /example for user-defined class(functor)map m2;map:iterator m2i, p1, p2;/map m2;/map :iterator m2i, p1, p2;m2“abd“ = 2;
31、 m2“abc“ = 1; m2“cba“ = 2;m2.insert(make_pair(“aaa“, 9);m2“abf“ = 4; m2“abe“ = 2;cout first second first second #include #include using namespace std;int main() multimap mm1;multimap:iterator mm1i, p1, p2;mm1.insert(make_pair(“b“, 3);mm1.insert(make_pair(“a“, 0);mm1.insert(make_pair(“b“, 5);mm1.inse
32、rt(make_pair(“c“, 4);mm1.insert(make_pair(“b“, 2);cout first second first second 实例化(set) : setSetName 实例化(multiset) : multisetSetName成员函数:构造函数(使得可以在定义时赋初值)set();set(const set (上面的 insert 对 multiset 无返回值)iterator insert(iterator loc, TYPE 插入一个元素, 对于 set 返回一个 pair分别是插入元素的迭代器和是否插入成功从 loc 开始寻找一个可以插入值为v
33、alue 的元素的位置将其插入并返回其迭代器插入start, end)之间的元素到容器中void erase(iterator loc)void erase(iterator start, iterator end)size_type erase(const key_type 返回一个迭代器,指向键值 = key 的第一个元素。iterator upper_bound( const key_type 返回一个迭代器,指向键值 key 的第一个元素。size_type size() 返回元素的数量。void swap( vector 交换两个链表中的元素STL 资料 2009 年21/43key
34、_compare key_comp(); 返回一个比较 key 的函数。value_compare value _comp(); 返回一个比较 value 的函数。reverse_iterator rbegin(); 返回一个逆向迭代器,指向链表的末尾reverse_iterator rend(); 返回一个指向开头之前位置的逆向迭代器Set 实例程序:#include #include #include using namespace std;struct T1 int key,value1, value2;bool operator s2; set s3;#if 1sets1;set:it
35、erator iter1;#elseset s1;set :iterator iter1;#endifs1.insert(“abc“); s1.insert(“abc“); s1.insert(“abc“);s1.insert(“bca“); s1.insert(“aaa“);cout #include #include using namespace std;struct T1 int key,value1, value2;bool operator s2;multiset s3;#if 1multisets1;multiset:iterator iter1;#elsemultiset s1
36、;multiset :iterator iter1;#endifs1.insert(“abc“); s1.insert(“abc“); s1.insert(“abc“);s1.insert(“bca“); s1.insert(“aaa“);cout :iterator s1i, p1, p2;p1 = s1.lower_bound(“abc“); p2 = s1.upper_bound(“abc“);for(s1i = p1; s1i != p2; s1i+)cout 实例化: dequeDequeName 成员函数:构造函数(使得可以在定义时赋初值)deque ();deque (size_
37、type n, const TYPE void assign(size_type num, const TYPE 清空 vector,插入区间start, end)的内容到 list 中清空 vector,插入 num 个值为 val 的元素TYPE at(size_type loc) 返回在 loc 位置元素的值的引用,有左值TYPE iterator erase(iterator start, iterator end);删除 loc 所指元素并返回下一元素迭代器删除start, end)之间的元素,并返回最后一个被删除元素的下个元素的迭代器iterator insert( iterato
38、r loc, const TYPE void insert( iterator loc, size_type num, const TYPE void insert( iterator loc, input_iterator start, input_iterator end );插入一个值为 value 的元素在 loc 位置并返回其迭代器,原 loc 及以后的元素后移。插入 num 个值为 value 的元素在 loc 位置,原 loc 及以后元素后移。插入start, end)之间的元素到 loc 位置,原 loc 及以后元素后移void pop_front(); 删除 deque 的第
39、一个元素。void push_front( const TYPE 将 val 放置到 deque 的开头。void pop_back(); 删除 deque 的最后一个元素。void push_back( const TYPE size_type size() 返回 list 中元素的数量。void resize( size_type n,TYPE val = 0)将 deque 大小重置为 n, 若 n #include #include using namespace std;int main() deque a;for (int i = 0; i /默认情况下包含了 iostream 就
40、可以用了实例化:string StringName;成员函数:构造函数string();string( const stringstring(size_type length, const charstring( const char* str, size_type length );string( const stringstring( input_iterator start, input_iterator end );无操作使用一个 string 来初始化使用 length 个字符 ch 来初始化使用一个字符数组初始化(ASCII0 结束)用一个字符数组最多前 length 个字符初始化
41、用一个 string 从 index 开始的最多length 个字符初始化用start, end)之间的元素来初始化=, =, !=, +, +=, , =, 可以像字符数组一样随机读取和写入stringstringstringstringstringstring末尾追加一个 string追加一个字符数组追加一个 string 从 index 开始的最多len 个字符追加一个字符数组最多 num 个字符追加 num 个字符 ch追加start, end)之间的元素void assign( size_type num, const charvoid assign( input_iterator
42、start, input_iterator end );stringstringstringstring赋值,用字符数组最多 num 个字符赋值,用 string 从 index 开始的最多 len 个字符TYPE 返回在指定位置 loc 的字符以读取或写入const_iterator begin() const; 返回指向头部的迭代器const char * c_str(); 返回一个标准 c 字符串,但是不允许修改,否则会破坏 string 的内部结构size_type capacity() const; 返回已分配空间可容纳的最大字符数void clear() 清空 string,但是不
43、回收空间int compare(string a, string b) 比较两个字符串,ab 返回正数, 可以使用字符数组。size_type copy( char* str, size_type num, size_type index = 0 ); /注意 !调用这个函数的时候会自动调用 memset(str, NULL, sizeof(str);将 string 中从 index(默认为 0)开始的最多 num 个字符 copy 到字符数组 str 中,返回 copy 的字符数。 不建议使用。const char *data(); 返回指向第一个字符的指针(不要修改!)bool empt
44、y() const; 返回 true 如果字符串长为 0const_iterator end() const; 返回指向最后一个字符下一位置的迭代器iterator erase( iterator loc );iterator erase( iterator start, iterator end );string删除 loc 位置的字符删除start,end)之间的字符删除从 index 开始的 num 个字符,返回*thissize_type find( const stringsize_type find( const char* str, size_type index );size_
45、type find( const char* str, size_type index, size_type length );size_type find( char ch, 返回从 index 开始 str 第一次出现的位置,找不到就返回 string:npos(常量)返回从 index 开始 str 第一次出现的位置,找不到就返回 string:npos(常量)返回从 index 开始 str 前 length 个字符第一次出现的位置,找不到就返回STL 资料 2009 年28/43size_type index ); string:npos(常量)返回从 index 开始,字符 ch
46、第一次出现的位置,找不到就返回 string:nposfind_first_not_of 格式同 find,返回第一个不是给定的字符串串中字符的位置find_first_of 格式同 find,返回第一个是给定的字符串串中字符的位置find_last_not_of 格式同 find,反向查找,返回第一个不是给定的字符串串中字符的位置find_last_of 格式同同 find,反向查找,返回第一个是给定的字符串串中字符的位置istream从输入流 is 中读入一些字符到 str 中,以 delimiter(默认为n)结束iterator insert( iterator i, const ch
47、arstringstringstringstringstringvoid insert( iterator i, size_type num, const charvoid insert( iterator i, iterator start, iterator end );在迭代器 i 指向的位置插入一个字符 ch在位置 index 插入一个 string在位置 index 插入一个 C 字符串在 index1 位置插入 string 从index2 开始的最多 num 个字符在 index 位置插入 C 字符串的最多 num个字符在 index 位置插入 num 个字符 ch在迭代器 i
48、指向的位置插入 num 个字符ch在迭代器 i 指向的位置插入start, end)之间的字符。size_type length() 返回 string 的长度(和 size()一样)size_type max_size() 返回字符串最大能容纳的字符数void push_back(char stringstringstringstringstringstringstringstring替换(从 index 开始最多 num 个字符)为(string str)替换从(index1 开始最多 num1 个字符)为(string str 从 index2 开始的最多num2 个字符 )替换(从 i
49、ndex 开始的最多 num 个字符)为(C 字符串 str)替换(从 index 开始最多 num1 个字符)为(C 字符串 str 中的 num2 个字符,有可能越界)替换(从 index 开始最多 num1 个字符)为(num2 个字符 ch)替换(本串中 start, nd)之间字符)为(string str)替换(本串中 start,end)之间字符)为(C 字符串 str)替换(本串中 start,end)之间字符)为(c 字符串 str 中最多 num 个字符,会越界)替换(本串中 start,end)之间字符)为 num 个字符 chvoid reserve( size_type size ); 为 string 开辟至少能寸下 size 个字符的内存,但不会删除现有字符void resize( size_