STL模板总结

                                            STL模板类总结
一 vector模板类
1 包含在头文件vector中,内部机理是使用动态内存分配。
2 如何定义vector类:     vector<string> str(5)//vector<string>::vector(int n);
3 []操作赋被重载,所以可以这样访问元素:str[n](n>=0 && n<5)。
4 vector模板类(包括STL模板)可以接受一个可选模板参数,该参数指定使用哪个分配器对象来管理内存。
    templae<class T, class Allocator=allocator<T> >
     class vector{ ... } 此参数可以省略,则容器将默认使用 allocator<T>类。这个类以标准方式使用new 和 delete.
5 size()方法,返回容器中元素数目。
6 swap()方法,交换两个容器的内容。vetor<string> a,b;
                                  a.swap(b);//交换a,b容器中的元素
7 begin() ,返回一个指向容器中第一个元素的迭代器;end(),返回超过容器尾的迭代器。
8 如何声明及使用迭代器。 vector<double>::iterator pd;//将 pd 声明为 vector 的 double 类型的迭代器
                         vector<double> scores
                         pd=scores.begin();
                         *pd=22.3;
                         ++pd;
  迭代器就像指针。
9 push_back()方法,将元素添加到矢量末尾,它负责内存管理,比如增加矢量长度,使之可以容纳新的成员。
                         vector<double> scores;
                         double temp;
                         scores.push_back(temp);
10 erase()方法,删除矢量中给定区间的元素,接受两个迭代器参数,参数指出要删除的区间。
                         erase(scores.begin(),scores.begin()+3);
11 insert()方法,与erase()功能相反。接受3个迭代器参数,第一个参数指定新元素的插入位置,第二,第三个迭代器指定了被插入区间。
                         vector<int> old;
                         vector<int> new;
                         old.insert(old.begin(),new.begin()+1,new.end());
12 for_each()函数,包括3个参数,前两个定义要执行的区间,最后一个是一个函数指针(函数对象),被指向的函数不能修改容器元素的值。
                          如果ShowReview( *pr)为一个排序函数
                          vector<int>::iterator pr;
                          vector<int> books;
                          for_each(books.begin(),books.end(),ShowReview);将对books排序。
13 random_shuffle()函数接受两个指定区间的迭代器参数,并对其随机排列,该容器必须支持随机访问。
                           random_shuffle(books.begin(),books.end());
14 sort()函数重载了两个版本,但对迭代器类必须支持随机访问。
             一,接受两个参数,这两个参数是区间的迭代器,功能是对该区间的元素进行升序排列。但是该容器类必须定义了operator<()函数。                     vector<int>::operator<()const;
                           vector<int> 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.rating<r2.rating)
                                  return true;
                               else
                                  return false;
                           }                
                           vector<Review> 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值
                            a<b;a>b;a<=b;a>=b;
三 STL的改进和模型
1 将指针用做迭代器:STL算法可用于普通指针。比如可以将sort函数用于数组:int a[5]; sort(a,a+4),对该数组排序。
2 copy()函数,3个参数,前两个表示要复制的范围,最后一个表示要复制的位置。前两个参数必须是输入迭代器,最后一个参数必须是输出迭代器。copy()函数可以覆盖目标容器中已有的数据,同时目标容器必须足够大,能够容纳被复制的元素。
3 ostream_iterator模板,输出迭代器的一个模型,也是适配器,该模板有两个参数。
                           #include<iterator>
                           ostream_iterator<int,char> out_iter(cout," ");
                           out_iter是一个接口,能够使用cout来显示信息,模板第一个参数int指出被发送给输出流的数据类型,第二个参数(char),指出了输出流使用的字符类型。构造函数的第一个参数,指出要使用的输出流,第二个字符串参数是在发送给输出流的每个数据项后显示的分隔符。             *out_iter++=15;  //works like cout<< 15 <<" "; 
                                vector<int> books;
                           copy(books.begin(),books.end(),out_iter);
4 istream_iterator模板,与ostream_iterator模板类似。
                           #include<iterator>
                           istream_iterator<int,char> in_iter(cin," ");模板第一个参数指出要输入的类型,第二个参数指出输入流使用的字符类型,用法同ostream_iterator.构造函数如果省略第二个参数,表示从输入流中读取,直到文件尾,类型不匹配或出现其他输入故障为止。
5 reverse_iterator迭代器,对其执行递增操作将导致被递减。rbegin()和rend(),前者返回指向超尾的反向迭代器,后者返回指向第一个元素的反向迭代器,执行递增将被递减。
                           ostream_iterator<int,char> out_iter(cout,' ');
                           vector<int> dice;
                           copy(dice.rbegin(),dice.rend(),out);反向输出dice容器中的元素。
                           不能对rbegin()进行解除引用。因为它指向超尾。
                            vector<int>::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<vector<int> > back_iter(dice);
                            vector<int> book;
                            copy(book.begin(),book.end(),back_iter); 插入到dice的尾部。
                            copy(book.begin(),book.end(),insert_iterator<vector<int> >(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<T,Alloc> &x) 将链表x与调用链表合并,两个链表必须已经排序,合并后,x为空,线性时间。
    2 void remove(const T & val) 从链表中删除val的所有实例,线性时间。
    3 sort(),使用<操作符对链表进行排序;n个元素的复杂度为n*log(n).
    4 void splice(iterator pos,list<T,Alloc>x),将链表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<int> pq1;
                            priority_queue<int> pq2 (greater<int>);使用greater<int>函数机制来确定。
(六) 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<string> A;
                           set<string,less<string> > B;第二个参数可选,第二个参数用来对关键字进行排序的比较函数或对象默认是(less<string> >)。
                            const int N=6;
                            string s1[N]={"buffoon","thinkers","for","heave","can","for"};
                            set<string> A(s1,s1+N);因为有两个for,所以只有5个元素
                            ostream_iterator<string,char> 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<string, char> out                                              (cout," "));显示A与B的并集
                                           set<string> c;
                                           set_union (A.begin(),A.end(),B.begin(),B.end(),insert_iterator<set<string> >                                                                                         (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:可反转,经过排序的联合容器,关键字类型与值类型不同,声明方式如下:
                                             multimap<int,string> codes;第一个模板参数指出关键字类型,第二个模板参数表明存储类型。还有一个可选的模板参数,指出用于对关键字进行排序的比较函数或对象,默认使用less<>模板,该模板将关键字作为参数。
                                             pair<const int,string> item (213,"Los Angeles");
                                             codes.insert(item);将按关键字类型 int排序插入到codes中。
                                             或者:codes.insert(pair<const int,string> (213,"Los Angeles"));
1 count()成员函数用关键字作为参数,返回具有该关键字元素的数目。
2 lower_bound(),upper_bound(),同set中的。
3 equal_range()函数,用关键字作为参数,返回表示与该关键字匹配的区间的迭代器(区间)              
                 pair<multimap<int, string>::iterator,multimap<int, string>::iterator> range=codes.equal_range(718);
                 cout << "Cities with area code 718: /n";
                 for(it=range.first;it!=range.second; ++i)
                      cout<<(*it).second <<endl;//first是关键字成员名,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<int> scores;
         scores.remove_if(tooBigs); 将删除 scores中大于100的元素。
         程序清单16.13 functor.cpp
         #include<iostream>
         #include<list>
         #include<iterator>
         template<class T>
         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<int> f100(100);
           list<int> yadayada;
           list<int> 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<int, char> out(cout," ");
           cout << "Original lists:/n";
           copy(yadayada.begin(),yadayada.end(), out);
           cout<<endl;
           copy(etcetera.begin(), etcetera.end(), out);
           cout<<endl;
           yadayada.remove_if(f100);//删除大于100的元素。
           etcetera.remove_if(TooBig<int> (200));//删除大于200的元素。
           cout<< "Trivved lists:/n";
           copy(yadayada.begin(),yadayada.end(), out);
           cout<<endl;
           copy(etcetera.begin(),etcetera.end(),out);
           cout<<endl;
           return 0;
         }  
(二)预定义的函数符
函数:transform()
      第一版本:接受4个参数,前两个参数指定容器区间的迭代器,第3个参数指定将结果复制到哪里的迭代器,最后一个参数是一个函数符,它被应用与区间中的每个元素,生成结果中的新元素。
       第二版本:接受5个参数,前两个参数指定第一容器区间的迭代器,第3个参数指定第二个容器区间的起始位置,第4个参数指定将结果复制到哪里,最后一个参数是一个函数符号,它被应用与两个区间中的每个元素。
           #include<functional>
           plus<double> add;
           transform(gr8.begin(),gr8.end(),m8.begin(),out,plus<double>());//将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<double>(),2.5)//将gr8中的每个元素乘以2.5,multiplies<double>()是二                                                                           元函数。(bind1s 和 bind2nd 用法相同)
六 算法
(一) algorithm 头文件中描述的:非修改式序列操作。
                                 修改式序列操作。
                                 排序和相关操作。
       numeric 头文件中描述的 :通用数字运算。
(二) STL 和 string 类
   包含begin(),end(),rbegin(),rend()等成员,可以使用STL接口。
    函数next_permutation()算法将区间内容转换为下一种排列方式。对于字符串,排列按照字母递增顺序进行,如果成功,返回 true,如果区间已经处于最后序列中,返回 false.
(三) 函数和容器方法
 一般STL方法比STL函数好,因为可以使用模板类的内存管理工具,可以自己调整容器长度,但STL函数可以用于数组,string类,STL容器。
    list<int> la;
    la.remove(4);//删除所有为4的元素,自动减小容器长度。
    remove(la.begin(),lb.end(),4);//删除所有为4的元素,将没被删除的排在容器前面,返回一个指向新的超尾值的迭代器,链表长度不变
 七 其他库
   vector ,valarray,都是数组模板。vector模板类支持面向容器的操作,如排序,插入,重新排列,搜索,将数据移到其他容器中等;   valarray类模板是面向数值计算的,不是STL的一部分,比如,没有 push_back(),insert()等等。
   valarray 重载了运算符。
         valarray<double> vad1(10),vad2(10),vad3(10);
         vector<double> ved1(10),ved2(10),ved3(10);
         vad3=vad1+vad2;//将对应的元素相加
         vad3=vad1*vad2;//将对应元素相乘
         vad3/=vad1; //重载了/=操作符
         transform(ved1.begin(),ved1.end(),ved2.begin(),ved3.begin(),plus<double>());
         transform(ved3.begin(),ved3.end(),ved3.begin(),bind1st(multiplies<double>(),2.5));//将ved3中每个元素乘以2.5
   valarray没有插入,排序,搜索等方法,有resize()方法,但不能自动调整valarray的大小。sort()函数用作valarray需要注意。
         valarray<double> vad(10);
         sort(vad,vad+10);//错误的,因为vad不是数组名,不能代表地址。
         sort(&vad[0],&vad[10]);//错误的,因为vad[10]是不确定的。
         sort(&vad[0],&vad[9]);
  slice对象可用做数组索引,被初始化为3个整数值:起始索引,索引数和跨距。起始索引是第一个被选中的元素的索引,索引数指出要选择多少个元素,跨距表示元素之间的间隔。
        valarray<int> varint;
        varint[slice(1,4,3)]=10;//varint[1]=10,varint[4]=10,varint[7]=10,varint[10]=10;
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值