STL模板总结 - mfkdyq的专栏 - CSDNBlog

来源:百度文库 编辑:神马文学网 时间:2024/06/03 14:08:40
STL模板总结
STL模板类总结
一 vector模板类
1 包含在头文件vector中,内部机理是使用动态内存分配。
2 如何定义vector类:     vector str(5)//vector::vector(int n);
3 []操作赋被重载,所以可以这样访问元素:str[n](n>=0 && n<5)。
4 vector模板类(包括STL模板)可以接受一个可选模板参数,该参数指定使用哪个分配器对象来管理内存。
templae >
class vector{ ... } 此参数可以省略,则容器将默认使用 allocator类。这个类以标准方式使用new 和 delete.
5 size()方法,返回容器中元素数目。
6 swap()方法,交换两个容器的内容。vetor a,b;
a.swap(b);//交换a,b容器中的元素
7 begin() ,返回一个指向容器中第一个元素的迭代器;end(),返回超过容器尾的迭代器。
8 如何声明及使用迭代器。 vector::iterator pd;//将 pd 声明为 vector 的 double 类型的迭代器
vector scores
pd=scores.begin();
*pd=22.3;
++pd;
迭代器就像指针。
9 push_back()方法,将元素添加到矢量末尾,它负责内存管理,比如增加矢量长度,使之可以容纳新的成员。
vector scores;
double temp;
scores.push_back(temp);
10 erase()方法,删除矢量中给定区间的元素,接受两个迭代器参数,参数指出要删除的区间。
erase(scores.begin(),scores.begin()+3);
11 insert()方法,与erase()功能相反。接受3个迭代器参数,第一个参数指定新元素的插入位置,第二,第三个迭代器指定了被插入区间。
vector old;
vector new;
old.insert(old.begin(),new.begin()+1,new.end());
12 for_each()函数,包括3个参数,前两个定义要执行的区间,最后一个是一个函数指针(函数对象),被指向的函数不能修改容器元素的值。
如果ShowReview( *pr)为一个排序函数
vector::iterator pr;
vector books;
for_each(books.begin(),books.end(),ShowReview);将对books排序。
13 random_shuffle()函数接受两个指定区间的迭代器参数,并对其随机排列,该容器必须支持随机访问。
random_shuffle(books.begin(),books.end());
14 sort()函数重载了两个版本,但对迭代器类必须支持随机访问。
一,接受两个参数,这两个参数是区间的迭代器,功能是对该区间的元素进行升序排列。但是该容器类必须定义了operator<()函数。                     vector::operator<()const;
vector vector_int;
sort(vector_int.begin(),vector_int.end()),将利用operator<()函数对其排序。
二,接受三个参数,前两个参数表示区间的迭代器,第三个参数是一个函数指针(函数对象),功能是用该函数指针指向的函数对区间元素进行的操作.
struct Review
{
string title;
int rating;
}
bool WorseThan(const Review & r1,const Review &r2)
{
if(r1.ratingreturn true;
else
return false;
}
vector books;
sort(books.begin(),books.end(),WorseThan);将按WorseThan机制对books排序。
二 迭代器类型(从程序的角度来说的)
1输入迭代器:对程序的输入,对容器其实是输出。该迭代器重载了*(解除引用操作符),++(递增操作符)。输入迭代器必须能够访问容器中的值。(注意:并不能保证输入迭代器第二次遍历容器时,顺序不变。另外,输入迭代器被递增后,也不能保证其先前的值仍然可以被解除引用,对输入迭代器的任何算法都应当是单通行的,不依赖前一次遍历时的迭代器值,也不依赖于本次遍历中的前面的迭代器的值,输入迭代器是单向的,可以递增,不能倒退)
2 输出迭代器:对容器是输入,操作符同输入迭代器。解除引用让程序能修改容器值,而不能读取。单通行的。
3 正向迭代器:使用++操作符来遍历容器,它总是按相同的顺序遍历一系列值。将正向迭代器递增后,仍然可以对前面的迭代器解除引用(如果保存了它) ,并可以得到相同的值。正向迭代器既可以读取和修改数据,也可以只能读取数据。
int *pirw; 既可以读也可以写
const int *pir;只能读
4 双向迭代器:能够双向遍历容器,具有正向迭代器的特征,支持前缀和后缀的递增,递减操作符。
5 随机访问迭代器,具有双向迭代器的特征,以下是除双向迭代器具有的特征之外的特征:
a和b是迭代器值,n为整数,r为随机迭代器变量或引用
a+n,n+a等效(a+n<=a.end())
a-n;r+=n;r-=n;a[n]
b-a为b=a+n中的n值
ab;a<=b;a>=b;
三 STL的改进和模型
1 将指针用做迭代器:STL算法可用于普通指针。比如可以将sort函数用于数组:int a[5]; sort(a,a+4),对该数组排序。
2 copy()函数,3个参数,前两个表示要复制的范围,最后一个表示要复制的位置。前两个参数必须是输入迭代器,最后一个参数必须是输出迭代器。copy()函数可以覆盖目标容器中已有的数据,同时目标容器必须足够大,能够容纳被复制的元素。
3 ostream_iterator模板,输出迭代器的一个模型,也是适配器,该模板有两个参数。
#include
ostream_iterator out_iter(cout," ");
out_iter是一个接口,能够使用cout来显示信息,模板第一个参数int指出被发送给输出流的数据类型,第二个参数(char),指出了输出流使用的字符类型。构造函数的第一个参数,指出要使用的输出流,第二个字符串参数是在发送给输出流的每个数据项后显示的分隔符。            *out_iter++=15;  //works like cout<< 15 <<" ";
vector books;
copy(books.begin(),books.end(),out_iter);
4 istream_iterator模板,与ostream_iterator模板类似。
#include
istream_iterator in_iter(cin,"");模板第一个参数指出要输入的类型,第二个参数指出输入流使用的字符类型,用法同ostream_iterator.构造函数如果省略第二个参数,表示从输入流中读取,直到文件尾,类型不匹配或出现其他输入故障为止。
5 reverse_iterator迭代器,对其执行递增操作将导致被递减。rbegin()和rend(),前者返回指向超尾的反向迭代器,后者返回指向第一个元素的反向迭代器,执行递增将被递减。
ostream_iterator out_iter(cout,‘ ‘);
vector dice;
copy(dice.rbegin(),dice.rend(),out);反向输出dice容器中的元素。
不能对rbegin()进行解除引用。因为它指向超尾。
vector::reverse_iterator rp;
如果rp指向位置6,则*rp为位置5的值。(先递减,在解除引用)
for(rp=dice.rbegin();rp!=dice.rend();rp++)
cout<<*rp;    反向输出元素
6 back_insert_iterator,front_insert_iterator,insert_iterator(都使用动态内存分配),将元素插入到容器,将复制转换为插入算法,插入算法比复制速度快。
back_insert_iterator > back_iter(dice);
vector book;
copy(book.begin(),book.end(),back_iter); 插入到dice的尾部。
copy(book.begin(),book.end(),insert_iterator>(dice,dice.begin()+1);插入到dice.begin()+1之前。
三 序列容器:元素按特定顺序排列,元素按严格的线性顺序排列
(一)vector:vector头文件中声明的,是数组的一种表示法,提供自动内存管理,可以动态改变vector对象的长度,提供了元素的随机访问,在尾部添加和删除元素的时间是固定的,但在中间或头部插入元素时间是线性的,vector强调快速访问。
1 是一个可反转容器,rbegin(),rend()方法,for_each(dice.rbegin,dice.rend(),Show),如果Show为显示函数,则反向显示dice容器中的元素。(reverse_iterator)
(二)deque(double-ended queue,双端队列):deque头文件中声明,支持随机访问。从deque对象的两端插入和删除元素时间是固定的,中部为线性时间(但是vector执行速度快)
(三)list(双向链表):list头文件中声明,可以双向遍历链表,在任意位置插入和删除时间是固定的,list强调元素的快速插入和删除。list是可反转容器,不支持数组表示法和随机访问。与其他不同的是:从容器中插入和删除元素之后,链表迭代器指向的元素不变。它是通过修改链表信息,使指向某个元素的迭代器任指向该元素,但它链表的元素可能与以前不同。以下是链表专用的成员函数:
1 void merge(list &x) 将链表x与调用链表合并,两个链表必须已经排序,合并后,x为空,线性时间。
2 void remove(const T & val) 从链表中删除val的所有实例,线性时间。
3 sort(),使用<操作符对链表进行排序;n个元素的复杂度为n*log(n).
4 void splice(iterator pos,listx),将链表x的内容插入到pos前面,x为空,固定时间。
5 void unique(),将连续的相同元素压缩为单个单元,线性时间。
(四) queue(适配器模板类,在queue头文件声明),不允许随机访问,甚至不允许遍历队列。使用限制在定义队列的基本操作上,可以将元素添加到对尾,从对首删除元素,查看对首和对尾的值,检查元素数目和测试队列是否为空。
1 bool empty()const
2 size_type size()const
3 T& front()
4 T& back()
5 void push(const T&x),在对尾插入x
6 void pop(),删除对首元素
(五) priority_queue (在queue头文件中声明,适配器模板类),最大元素被移到对首,默认底层类是vector,可以修改用于确定哪个元素放到对首的比较方式,提供一个可选构造函数参数即可。
priority_queue pq1;
priority_queue pq2 (greater);使用greater函数机制来确定。
(六) stack(在stack头文件中声明,适配器模板类),不允许随机访问,甚至不允许遍历堆栈,使用限制在定义堆栈的基本操作上。
1 bool empty()const
2 size_type size()const
3 T& top(),返回指向栈顶元素的引用
4 void push(const T&x) ,在堆栈顶部插入x
5 void pop(),删除堆栈顶部元素。
四 联合容器:允许插入新元素,不过不能指定元素的插入位置,将关键字看作常量,联合容器通常包含用于确定数据放置位置的算法,以便能很快检索信息.(set,multiset,map,multimap)
(一)set:值的类型与关键字相同,关键字是唯一的,一个联合集合,可反转,可排序,关键字是唯一的,所以只能存储同一种类型的值。
set A;
set > B;第二个参数可选,第二个参数用来对关键字进行排序的比较函数或对象默认是(less >)。
const int N=6;
string s1[N]={"buffoon","thinkers","for","heave","can","for"};
set A(s1,s1+N);因为有两个for,所以只有5个元素
ostream_iterator out (cout,‘ ‘);
copy(A.begin(),A.end(),out);输出结果为:buffoon can for heavy thinkers 由于关键字是唯一的,集合被排序,for也只出现一次。
1 set_union()函数(并集),接受5个迭代器参数,前两个迭代器定义了一个集合的区间,接下来的两个参数定义了第二个集合的区间,最后一个迭代器是输出迭代器,指出结果复制到什么位置。
set_union(A.begin(),A.end(),B.begin(),B.end(),ostream_iterator out                                              (cout,""));显示A与B的并集
set c;
set_union(A.begin(),A.end(),B.begin(),B.end(),insert_iterator>                                                                                        (c,c.begin() ) );把A与B的并集放到C中
2 set_intersection()函数,查找交集,接口与set_union()相同。
3 set_difference()函数,获得两个集合的差,接口同set_union()。两个集合的差是第一个集合减去两个集合公有的元素。
4 lower_bound()函数,将关键字作为参数,并返回一个迭代器,该迭代器指向集合中第一个小于关键字参数的成员。
5 upper_bound()函数,返回第一个大于关键字参数的成员。
6 insert()函数                               string s("tennis");
A.insert(s);
B.insert(A.begin(),A.end());因为排序决定了插入位置,所以这种类包含只指定要插入                                                                          的信息,而不指定位置。
(二)multimap:可反转,经过排序的联合容器,关键字类型与值类型不同,声明方式如下:
multimapcodes;第一个模板参数指出关键字类型,第二个模板参数表明存储类型。还有一个可选的模板参数,指出用于对关键字进行排序的比较函数或对象,默认使用less<>模板,该模板将关键字作为参数。
pair item (213,"Los Angeles");
codes.insert(item);将按关键字类型 int排序插入到codes中。
或者:codes.insert(pair (213,"Los Angeles"));
1 count()成员函数用关键字作为参数,返回具有该关键字元素的数目。
2 lower_bound(),upper_bound(),同set中的。
3 equal_range()函数,用关键字作为参数,返回表示与该关键字匹配的区间的迭代器(区间)
pair::iterator,multimap::iterator> range=codes.equal_range(718);
cout << "Cities with area code 718: \n";
for(it=range.first;it!=range.second; ++i)
cout<<(*it).second <五 函数对象 :函数符,可以是函数方式或重载了()操作符的类对象
(一)函数符概念:1 生成器(generator)是不用参数就可以调用的函数符。
2 一元函数(unary function)是用一个参数可以调用的函数符。
3 二元函数(binary function)是用两个参数可以调用的函数符。
4 返回bool值的一元函数是断言(predicate).
5 返回bool值的二元函数是二元断言(binary predicate).
list 模板有一个将断言作为参数的 remove_if()成员,该函数将断言应用于区间中的每个元素,如果断言为true,则删除该元素。
bool tooBig(int n){return n>100;}
list scores;
scores.remove_if(tooBigs); 将删除 scores中大于100的元素。
程序清单16.13 functor.cpp
#include
#include
#include
template
class TooBig
{
private:
T cutoff;
public:
TooBig(const T &t):cutoff(t){}
bool operator()(const T &v){return v>cutoff;}
};
int main()
{
using namespace std;
TooBig f100(100);
list yadayada;
list etcetera;
int vals[10] = {50,100,90,180,60,210,415,88,188,201};
yadayada.insert(yadayada.begin(),vals,vals + 10);
etcetera.insert(etcetera.begin(),vals,vals + 10);
ostream_iterator out(cout," ");
cout << "Original lists:\n";
copy(yadayada.begin(),yadayada.end(), out);
cout<copy(etcetera.begin(), etcetera.end(), out);
cout<yadayada.remove_if(f100);//删除大于100的元素。
etcetera.remove_if(TooBig (200));//删除大于200的元素。
cout<< "Trivved lists:\n";
copy(yadayada.begin(),yadayada.end(), out);
cout<copy(etcetera.begin(),etcetera.end(),out);
cout<return 0;
}
(二)预定义的函数符
函数:transform()
第一版本:接受4个参数,前两个参数指定容器区间的迭代器,第3个参数指定将结果复制到哪里的迭代器,最后一个参数是一个函数符,它被应用与区间中的每个元素,生成结果中的新元素。
第二版本:接受5个参数,前两个参数指定第一容器区间的迭代器,第3个参数指定第二个容器区间的起始位置,第4个参数指定将结果复制到哪里,最后一个参数是一个函数符号,它被应用与两个区间中的每个元素。
#include
plus add;
transform(gr8.begin(),gr8.end(),m8.begin(),out,plus());//将gr8和m8中的元素分别相加,将结果输出。
操作符和相应的函数符:在 functional 头文件中
+ plus                          > greater
- minus                         < less
* multiplies                    >= greater_equal
/ divides                       <= less_equal
% modulus                       && logical_and
== equal_to
- negate                        || logical_or
!= not_equal_to                  ! logical_not
(三) 自适应函数符和函数适配器
transform(gr8.begin(),gr8.end(),out,bind1st(multiplies(),2.5)//将gr8中的每个元素乘以2.5,multiplies()是二                                                                          元函数。(bind1s 和 bind2nd 用法相同)
六 算法
(一) algorithm 头文件中描述的:非修改式序列操作。
修改式序列操作。
排序和相关操作。
numeric 头文件中描述的 :通用数字运算。
(二) STL 和 string 类
包含begin(),end(),rbegin(),rend()等成员,可以使用STL接口。
函数next_permutation()算法将区间内容转换为下一种排列方式。对于字符串,排列按照字母递增顺序进行,如果成功,返回 true,如果区间已经处于最后序列中,返回 false.
(三) 函数和容器方法
一般STL方法比STL函数好,因为可以使用模板类的内存管理工具,可以自己调整容器长度,但STL函数可以用于数组,string类,STL容器。
list la;
la.remove(4);//删除所有为4的元素,自动减小容器长度。
remove(la.begin(),lb.end(),4);//删除所有为4的元素,将没被删除的排在容器前面,返回一个指向新的超尾值的迭代器,链表长度不变
七 其他库
vector,valarray,都是数组模板。vector模板类支持面向容器的操作,如排序,插入,重新排列,搜索,将数据移到其他容器中等;  valarray类模板是面向数值计算的,不是STL的一部分,比如,没有 push_back(),insert()等等。
valarray 重载了运算符。
valarray vad1(10),vad2(10),vad3(10);
vector ved1(10),ved2(10),ved3(10);
vad3=vad1+vad2;//将对应的元素相加
vad3=vad1*vad2;//将对应元素相乘
vad3/=vad1; //重载了/=操作符
transform(ved1.begin(),ved1.end(),ved2.begin(),ved3.begin(),plus());
transform(ved3.begin(),ved3.end(),ved3.begin(),bind1st(multiplies(),2.5));//将ved3中每个元素乘以2.5
valarray没有插入,排序,搜索等方法,有resize()方法,但不能自动调整valarray的大小。sort()函数用作valarray需要注意。
valarray vad(10);
sort(vad,vad+10);//错误的,因为vad不是数组名,不能代表地址。
sort(&vad[0],&vad[10]);//错误的,因为vad[10]是不确定的。
sort(&vad[0],&vad[9]);
slice对象可用做数组索引,被初始化为3个整数值:起始索引,索引数和跨距。起始索引是第一个被选中的元素的索引,索引数指出要选择多少个元素,跨距表示元素之间的间隔。
valarray varint;
varint[slice(1,4,3)]=10;//varint[1]=10,varint[4]=10,varint[7]=10,varint[10]=10;
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1594983