《STL》— STL 详解

 

STL学习系列——标准模板库STL介绍

 

       库是一系列程序组件的集合,他们可以在不同的程序中重复使用。C++语言按照传统的习惯,提供了由各种各样的函数组成的库,用于完成诸如输入/输出、数学计算等功能。

1. STL介绍

标准模板库STL是当今每个从事C++编程的人需要掌握的技术,所有很有必要总结下

本文将介绍STL并探讨它的三个主要概念:容器、迭代器、算法

STL的最大特点就是:

数据结构和算法的分离,非面向对象本质。访问对象是通过象指针一样的迭代器实现的;

容器是象链表,矢量之类的数据结构,并按模板方式提供;

算法是函数模板,用于操作容器中的数据。由于STL以模板为基础,所以能用于任何数据类型和结构。

容器可以分为三种主要类型:序列容器、关联容器、容器适配器。

每种STL容器都具有相关联的成员函数,这些成员函数的一个子集在所有的STL容器中都定义了。

STL迭代器的属性和指针类似,程序可以利用迭代器操作STL容器中的元素

STL算法是用于执行常见数据操作的函数,这些操作包括搜索、排序和比较元素,STL提供了大约70种算法,其中大多数算法都使用迭代器来访问容器元素。

1.1   容器简介

 容器可以分为三种:序列容器、关联容器、容器适配器。

序列容器:vector deque list

Vector:可从后端执行快速的插入和删除,直接访问任何元素

Deque:从前面或后面执行快速的插入和删除,直接访问任何元素

List:双链表,能在任何地方执行快速的插入和删除

关联容器:set multiset map multimap

Set:执行快速搜索,元素不允许重复

Multiset:执行快速搜索,元素允许重复

Map:一对一映射,元素不允许重复,快速的基于键的搜索

Multimap:一对多映射,元素允许重复,快速的基于键的搜索

容器适配器:stack queue priority_queue

Stack:后进先出

Queue:先进先出

priority_queue:优先级最高的元素总是最先出队

序列容器表示线性数据结构,例如向量和链表;

关联容器是非线性容器,通常能够快速找出保存在容器中的元素。这类容器能够保存值的集合或键/值对;序列容器和关联容器统称为第一类容器。

STL将堆栈和队列实现为容器适配器,使程序以一种受约束的方式看待序列容器。

STL通常可通过模板实现泛型编程,以避免继承和虚函数,获得更好的执行时性能。

1.2   迭代器简介

迭代器在许多方面和指针相同,用于指向第一类容器的元素。

迭代器提供对一个容器中的对象的访问方法,并且定义了容器中对象的范围。迭代器就如同一个指针。事实上,C++的指针也是一种迭代器。但是,迭代器不仅仅是指针,因此你不能认为他们一定具有地址值。例如,一个数组索引,也可以认为是一种迭代器。

迭代器有各种不同的创建方法。程序可能把迭代器作为一个变量创建。一个STL容器类可能为了使用一个特定类型的数据而创建一个迭代器。作为指针,必须能够使用*操作符类获取数据。你还可以使用其他数学操作符如++。典型的,++操作符用来递增迭代器,以访问容器中的下一个对象。如果迭代器到达了容器中的最后一个元素的后面,则迭代器变成past-the-end值。使用一个past-the-end值得指针来访问对象是非法的,就好像使用NULL或为初始化的指针一样。

废话不多说,直接上demo

[cpp] view plaincopy

  1. //利用istream_iterator进行输入,利用ostream_iterator进行输出  
  2. //下面程序演示了使用istream_iterator从标准输入进行输入,以及使用ostream_iterator输出到标准输出  
  3. #include "stdafx.h"  
  4. #include <iostream>  
  5. using namespace std;  
  6.   
  7. #include <iterator>  
  8.   
  9. int _tmain(int argc, _TCHAR* argv[])  
  10. {  
  11.  cout<<"输入2个整数:"<<endl;  
  12.  //下行创建了一个istream_iterator,它能够以一种类型安全的方式从标准输入对象cin提取int值  
  13.  std::istream_iterator<int> inputInt(cin);  
  14.   
  15.  //下行对迭代器inputInt解除引用,并从cin中读出一个整数,然后将它赋予number1  
  16.  int number1=*inputInt;  
  17.  ++inputInt;                    //将迭代器inputInt定位到输出流中的下一个值  
  18.  int number2=*inputInt;         //从inputInt输入下一个整数,并将它赋予number2  
  19.   
  20.  //下行创建了一个ostream_iterator,它能够在标准输出对象cout中出入int值  
  21.  std::ostream_iterator<int> outputInt(cout);  
  22.  cout<<"和是:"<<endl;  
  23.  *outputInt=number1+number2; //将number1和number2的和赋予*outputInt  
  24.  cout<<endl;  
  25.  system("pause");  
  26.  return 0;  
  27. }  

1.3   算法简介

STL算法能用于各种容器。STL提供的许多算法,大量用于操作容器,插入、删除、搜索、排序以及其他算法,都适合于部分或者所有的STL容器。

STL的实现非常简单。到目前为止,类的设计者都将算法作为容器的成员函数,使算法和容器相关联。STL采用不同的方法,STL的算法和容器是分离的,它只是间接地通过迭代器操作容器的元素。

STL算法能够用于STL容器以及基于指针的、C风格的数组。

STL:STL各种容器的使用时机详解

 

C++标准程序库提供了各具特长的不同容器。现在的问题是:该如何选择最佳的容器类别?下表给出了概述。

但是其中有些描述可能不一定实际。例如:如果你需呀处理的元素数量很少,可以虎落复杂度,因为线性算法通常对元素本身的处理过程比较快,这种情况下,“显性复杂度搭配快速的元素处理”要比“对数复杂度搭配慢的元素处理”来得划算。

    作为对上表的补充,使用时:

    1.缺省情况下应该使用vector。vector的内部结构最简单,并允许随机存取,所以数据的存取十分方便灵活,数据的处理也够快。

    2.如果经常要在序列头部和尾部安插和移除元素,应该采用deque。如果你希望元素被移除时,容器能够自动缩减内存,那么你也应该采用deque。此外,由于vector通常才有用一个内存区块来存放元素,而deque采用多个区块,所以后者可内含更多元素。

   3.如果需要经常在容器的中段执行元素的安插、移除和移动,可考虑使用list。list提供特殊的成员函数,可以在常数时间内将元素从A容器转移到B容器。但由于list不支持随机存取,所以如果只要知道list的头部却要造访list中的元素,性能会大打折扣。

     和所有“以节点为基础”的容器相似,只要元素还是容器的已不复,list就不会令指向那些元素的迭代器失效。vector则不然,一旦超过其容量,它的所有iterators,pointers.references都会失效;执行安插或移除操作时,也会令一部分iterators、pointers、references失效。至于deque,当它的大小改变,所有iterators,pointers,references都会失效。

    4.如果你要的容器是这种性质:每次操作若不成功,便无效用,那么你应该选用list,或是采用关联式容器。

    5.如果你经常需要根据某个准则来搜寻元素,那么应当使用“以该排序准则对元素进行排序”的set或multiset。记住,理论上,面对1000个元素的排序,对数复杂度比线性复杂度好10倍。就搜寻速度而言,hash table通常比二叉树还要快5-10倍。但是hash table的元素并未排序,所以如果元素必须排序,它就用不上了。

    6.如果想处理key/value pair,请采用map或multimap。

    7.如果需要关联式数组,应采用map。

    8.如果需要字典结构,应采用multimap。 

                                     二、STL:map/multimap用法详解

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

          使用map/multimap之前要加入头文件#include<map>,map和multimap将key/value当作元素,进行管理。它们可根据key的排序准则自动将元素排序。multimap允许重复元素,map不允许重复元素。

          map和multimap内部的数据结构也是平衡二叉树。

          map和multimap根据元素的key自动对元素进行排序,要修改元素的key必须先删除拥有该key的元素,然后插入拥有新的key/value的元素。

常用函数

1.构造函数和析构函数    

map m:创建空映射,不包含任何元素

map m(op):以op为排序准则,产生一个空的map

map m1(m2):复制c2中的元素到c1中

map m(const value_type *first, const value_type* last):复制[first, last)之间元素构成新映射

map m(const value_type *first, const value_type* last,op):以op为排序准则,复制[first, last)之间元素构成新映射。

m.~set()销毁所有元素,释放内存

 

multimap mm:创建空映射,不包含任何元素

multimap mm(op):以op为排序准则,产生一个空的multimap

multimap m1(m2):复制m2中的元素到m1中

multimap m(const value_type *first, const value_type* last):复制[first, last)之间元素构成新映射

multimap m(const value_type *first, const value_type* last,op):以op为排序准则,复制[first, last)之间元素构成新映射

m.~multimap()销毁所有元素,释放内存

 

[cpp] view plaincopy

  1. #include "stdafx.h"  
  2. #include <iostream>  
  3. #include <map>  
  4.   
  5. using namespace std;  
  6.   
  7. bool fncomp (char lhs, char rhs) { return lhs<rhs;}  
  8.   
  9. struct classcomp {  
  10.     bool operator() (const char& lhs, const char& rhs) const  
  11.     { return lhs<rhs;}  
  12. };  
  13.   
  14. int main ()  
  15. {  
  16.     map<char,int> first;  
  17.   
  18.     first['a']=10;  
  19.     first['b']=30;  
  20.     first['c']=50;  
  21.     first['d']=70;  
  22.   
  23.     map<char,int> second (first.begin(),first.end());  
  24.   
  25.     map<char,int> third (second);  
  26.   
  27.     map<char,int,classcomp> fourth;                 // class as Compare  
  28.   
  29.     bool(*fn_pt)(char,char) = fncomp;  
  30.     map<char,int,bool(*)(char,char)> fifth (fn_pt); // function pointer as Compare  
  31.   
  32.     return 0;  
  33. }  

 

2.大小、判断空函数

    int size() const:返回容器元素个数
    bool empty() const:判断容器是否空,若返回true,表明容器已空。

3.增加删除函数

    iterator insert(const value_type& x):插入元素x

    iterator insert(iterator it,const value_type& x):在迭代指针it处插入元素x
    void insert(const value_type *first,const value_type* last):插入[first, last)之间元素

    iterator erase(iterator it):删除迭代指针it处元素

    iterator erase(iterator first,iterator last):删除[first, last)之间元素

    size_type erase(const Key& key):删除键值等于key的元素

 

[cpp] view plaincopy

  1. #include "stdafx.h"  
  2. #include <iostream>  
  3. #include <map>  
  4.   
  5. using namespace std;  
  6.   
  7.   
  8. int main ()  
  9. {  
  10.     map<char,int> mymap;  
  11.   
  12.     mymap.insert(pair<char,int>('a',10));  
  13.     mymap.insert(pair<char,int>('z',200));  
  14.   
  15.     pair<map<char,int>::iterator,bool> ret;  
  16.     ret = mymap.insert(pair<char,int>('z',500));  
  17.     if (ret.second == false)  
  18.     {  
  19.         cout<<"element 'z' already existed";  
  20.         cout<<"with a value of "<<ret.first->second<<'\n';  
  21.     }  
  22.   
  23.     map<char,int>::iterator it = mymap.begin();  
  24.     mymap.insert(it,pair<char,int>('b',300));  
  25.     mymap.insert(it,pair<char,int>('c',400));  
  26.   
  27.     map<char,int> anothermap;  
  28.     anothermap.insert(mymap.begin(),mymap.find('c'));  
  29.   
  30.     cout<<"mymap contains :\n";  
  31.     for (it = mymap.begin();it!= mymap.end();it++)  
  32.     {  
  33.         cout<<it->first<<"=>"<<it->second<<'\n';  
  34.     }  
  35.   
  36.     cout<<"anothermap contains :\n";  
  37.     for (it = anothermap.begin();it!= anothermap.end();it++)  
  38.     {  
  39.         cout<<it->first<<"=>"<<it->second<<'\n';  
  40.     }  
  41.     return 0;  
  42. }  

上述代码运行结果为

 

 

[cpp] view plaincopy

  1. #include "stdafx.h"  
  2. #include <iostream>  
  3. #include <map>  
  4.   
  5. using namespace std;  
  6.   
  7.   
  8. int main ()  
  9. {  
  10.     map<char,int> mymap;  
  11.     map<char,int>::iterator it;  
  12.       
  13.     mymap['a'] = 10;  
  14.     mymap['b'] = 20;  
  15.     mymap['c'] = 30;  
  16.     mymap['d'] = 40;  
  17.     mymap['e'] = 50;  
  18.     mymap.insert(pair<char,int>('f',60));  
  19.   
  20.     cout<<"initial mymap contains :\n";  
  21.     for (it = mymap.begin();it!= mymap.end();it++)  
  22.     {  
  23.         cout<<it->first<<"=>"<<it->second<<'\n';  
  24.     }  
  25.   
  26.     it = mymap.find('b');  
  27.     mymap.erase(it);  
  28.   
  29.     mymap.erase('c');  
  30.   
  31.     it = mymap.find('e');  
  32.     mymap.erase(it,mymap.end());  
  33.   
  34.     cout<<"now mymap contains :\n";  
  35.     for (it = mymap.begin();it!= mymap.end();it++)  
  36.     {  
  37.         cout<<it->first<<"=>"<<it->second<<'\n';  
  38.     }  
  39.   
  40.     return 0;  
  41. }  

上述代码运行结果为:

 

如果想往map/multimap中修改一个映射的值,应先插入一个新映射,再把与修改的映射删除。

4.遍历函数    

    iterator begin():返回首元素的迭代器指针

    iterator end():返回尾元素的迭代器指针

    reverse_iterator rbegin():返回尾元素的逆向迭代器指针

    reverse_iterator rend():返回首元素前一个位置的迭代器指针

5.操作函数   

    const_iterator lower_bound(const Key& key):返回键值大于等于key的迭代器指针
    const_iterator upper_bound(const Key& key):返回键值大于key的迭代器指针
    int count(const Key& key) const:返回键值等于key的元素的个数
    pair<const_iterator,const_iterator> equal_range(const Key& key) const:返回容器中键值等于key的迭代指针[first, last)
    const_iterator find(const Key& key) const:查找功能,返回键值等于key的迭代器指针
    void swap(set& s):交换但映射元素
    void swap(multiset& s):交换多映射元素  

6.特殊函数

    reference operator[](const Key& k):仅在但映射map类中,可以以数组的形式给映射添加键-值对,并可返回值的引用。

                               三、STL:set/multiset用法详解

 

        使用set或multiset之前,必须加入头文件<set>

Set、multiset都是集合类,差别在与set中不允许有重复元素,multiset中允许有重复元素。

sets和multiset内部以平衡二叉树实现

 

1.   常用函数

1)        构造函数和析构函数

set c:创建空集合,不包含任何元素

set c(op):以op为排序准则,产生一个空的set

set c1(c2):复制c2中的元素到c1中

set c(const value_type *first, const value_type* last):复制[first, last)之间元素构成新集合

set c(const value_type *first, const value_type* last,op):以op为排序准则,复制[first, last)之间元素构成新集合。

c.~set()销毁所有元素,释放内存

 

multiset mc:创建空集合,不包含任何元素

multiset mc(op):以op为排序准则,产生一个空的set

multiset c1(c2):复制c2中的元素到c1中

multiset c(const value_type *first, const value_type* last):复制[first, last)之间元素构成新集合

multiset c(const value_type *first, const value_type* last,op):以op为排序准则,复制[first, last)之间元素构成新集合。

c.~set()销毁所有元素,释放内存

 

[cpp] view plaincopy

  1. // constructing sets  
  2. #include <iostream>  
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值