STL基础学习(STL中的容器解析、代码展示、例题分析,帮助你学STL)

STL就是Standard Template Library(C++标准模板库),下面是关于STL中的各种内容

STL中的几个基本概念:

1.容器:可容纳各种数据类型的数据结构。

可以用于存放各种类型的数据(基本类型的变量,对象等)的数据结构。
容器分为三大类:
(1) 顺序容器  
vector:后部插入/删除,直接访问 deque:前/后部插入/删除,直接访问 list:双向链表,任意位置插入/删除

1) vector  头文件 <vector>
    实际上就是个动态数组。随机存取任何元素都能在常数时间完成。在尾端增删元素具有较佳的性能。
 2) deque   头文件 <deque>
    也是个动态数组,随机存取任何元素都能在常数时间完成(但性能次于vector)。在两端增删元素具有较佳的性能。
 3) list    头文件 <list> 
    双向链表,在任何位置增删元素都能在常数时间完成。不支持随机存取。
   上述三种容器称为顺序容器,是因为元素的插入位置同元素的值无关。
( 2)关联容器
set:快速查找,无重复元素 multiset :快速查找,可有重复元素 map:一对一映射,无重复元素,基于关键字查找 multimap :一对一映射,可有重复元素,基于关键字查找,前2者合称为第一类容器 

关联式容器内的元素是排序的,插入任何元素,都按相应的排序准则来确定其位置。关联式容器的特点是在查找时具有非常好的性能。
1) set/multiset:   头文件 <set>
   set 即集合。set中不允许相同元素,multiset中允许存在相同的元素。
2) map/multimap:   头文件 <map>
   map与set的不同在于map中存放的是成对的key/value。
   并根据key对元素进行排序,可快速地根据key来检索元素
   map同multimap的不同在于是否允许多个元素有相同的key值。
   上述4种容器通常以平衡二叉树方式实现,插入和检索的时间都是 O(logN)
(3)容器适配器
stack:LIFO queue:FIFO priority_queue:优先级高的元素先出 

对象被插入容器中时,被插入的是对象的一个复制品。
许多算法,比如排序,查找,要求对容器中的元素进行比较,所以,放入容器的对象所属的类,还应该实现 == 和 < 运算符。
1) stack  :头文件 <stack>
栈。是项的有限序列,并满足序列中被删除、检索和修改的项只能是最近插入序列的项。即按照后进先出的原则
2) queue :头文件 <queue>
   队列。插入只可以在尾部进行,删除、检索和修改只允许从头部进行。按照先进先出的原则。
3)priority_queue :头文件 <queue>
优先级队列。最高优先级元素总是第一个出列

所有标准库容器共有的成员函数:
相当于按词典顺序比较两个容器大小的运算符:   =, < , <= , >  , >=, == , !=
empty : 判断容器中是否有元素
max_size: 容器中最多能装多少元素
size:   容器中元素个数
swap: 交换两个容器的内容
只在第一类容器中的函数:
begin  返回指向容器中第一个元素的迭代器
end     返回指向容器中最后一个元素后面的位置的迭代器
rbegin  返回指向容器中最后一个元素的迭代器
rend    返回指向容器中第一个元素前面的位置的迭代器
erase   从容器中删除一个或几个元素
clear   从容器中删除所有元素

2.迭代器:可依次存取容器中元素的东西

用于指向第一类容器中的元素。有const 和非 const两种。
通过迭代器可以读取它指向的元素,通过非const迭代器还能修改其指向的元素。迭代器用法和指针类似。
定义一个容器类的迭代器的方法可以是:
容器类名::iterator   变量名;
或:
容器类名::const_iterator 变量名;
访问一个迭代器指向的元素:
* 迭代器变量名
迭代器上可以执行 ++ 操作, 以指向容器中的下一个元素。如果迭代器到达了容器中的最后一个元素的后面,则迭代器变成past-the-end值。
使用一个past-the-end值的迭代器来访问对象是非法的,就好像使用NULL或未初始化的指针一样。

算法:用来操作容器中的元素的函数模板。例如,STL用sort()来对一个vector中的数据进行排序,用find()来搜索一个list中的对象。
函数本身与他们操作的数据的结构和类型无关,因此他们可以在从简单数组到高度复杂容器的任何数据结构上使用。
比如,数组int array[100]就是个容器,而 int * 类型的指针变量就可以作为迭代器,可以为这个容器编写一个排序的算法,以下是各种算法:

#include <vector>
#include <iostream>
using namespace std;
int main()  {
vector<int> v; //一个存放int元素的向量,一开始里面没有元素
v.push_back(1);
v.push_back(2); 
v.push_back(3);  
v.push_back(4);
vector<int>::const_iterator i;   //常量迭代器
for( i = v.begin();i != v.end();i ++ ) 
cout << * i << ",";
cout << endl;

vector<int>::reverse_iterator r;  //反向迭代器
for( r = v.rbegin();r != v.rend();r++ ) 
cout << * r << ",";
cout << endl;
vector<int>::iterator j;   //非常量迭代器
for( j = v.begin();j != v.end();j ++ ) 
* j =  100;
for( i = v.begin();i != v.end();i++ ) 
cout << * i << ",";
}
输出结果:
1,2,3,4,
4,3,2,1,
100,100,100,100,

STL 中的迭代器按功能由弱到强分为5种:
   1. 输入:Input iterators 提供对数据的只读访问。
   1. 输出:Output iterators 提供对数据的只写访问
   2. 正向:Forward iterators 提供读写操作,并能一次一个地向前推进迭代器。
   3. 双向:Bidirectional iterators提供读写操作,并能一次一个地向前和向后移动。
   4. 随机访问:Random access iterators提供读写操作,并能在数据中随机移动。
编号大的迭代器拥有编号小的迭代器的所有功能,能当作编号小的迭代器使用。

不同迭代器所能进行的操作(功能):

所有迭代器: ++p, p ++
输入迭代器: * p, p = p1, p == p1 , p!= p1
输出迭代器: * p, p = p1
正向迭代器: 上面全部
双向迭代器: 上面全部,--p, p --,
随机访问迭代器: 上面全部,以及:
p+= i, p -= i, 
p + i: 返回指向 p 后面的第i个元素的迭代器
p - i: 返回指向 p 前面的第i个元素的迭代器
p[i]:  p 后面的第i个元素的引用
p < p1, p <= p1, p > p1, p>= p1
容器所支持的迭代器类别:

容器 迭代器类别
vector 随机
deque 随机
list  双向
set/multiset 双向
map/multimap 双向
stack 不支持迭代器
queue 不支持迭代器
priority_queue 不支持迭代器
例如,vector的迭代器是随机迭代器,所以遍历 vector 可以有以下几种做法:
vector<int> v(100);
vector<int>::value_type i; //等效于写 int i;(P687)
for(i = 0;i < v.size() ; i ++)
cout << v[i];
vector<int>::const_iterator ii;
for( ii = v.begin(); ii != v.end ();ii ++ )
cout << * ii;
//间隔一个输出:
ii = v.begin();
while( ii < v.end()) {
cout << * ii;  
ii = ii + 2; 
}

而 list 的迭代器是双向迭代器,所以以下代码可以:
list<int> v;
list<int>::const_iterator ii;
for( ii = v.begin(); ii != v.end ();ii ++ )
cout << * ii;
以下代码则不行:
for( ii = v.begin(); ii < v.end ();ii ++ )
cout << * ii;
//双向迭代器不支持 <
for(int i = 0;i < v.size() ; i ++)
cout << v[i]; //双向迭代器不支持 []
例子:

#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
main()  {
int array[10] = {10,20,30,40};
vector<int> v;
v.push_back(1); v.push_back(2);
v.push_back(3); v.push_back(4);
vector<int>::iterator p;
p = find(v.begin(),v.end(),3);
if( p != v.end())
cout << * p << endl;
p = find(v.begin(),v.end(),9);
if( p == v.end())
cout << "not found " << endl;
p = find(v.begin()+1,v.end()-2,1);
if( p != v.end())
cout << * p << endl;
int * pp = find( array,array+4,20);
cout << * pp << endl;
}
输出:
3
not found
3
20


例:
int main()  { int i;
int a[5] = {1,2,3,4,5 };    vector<int>  v(5);
cout << v.end()  - v.begin() << endl;
for( i = 0;i < v.size();i ++ )  v[i] = i;
v.at(4) = 100;
for( i = 0;i < v.size();i ++ )
cout << v[i] << "," ;
cout << endl;
vector<int> v2(a,a+5);  //构造函数
v2.insert( v2.begin() + 2, 13 ); //在begin()+2位置插入 13
for( i = 0;i < v2.size();i ++ )
cout << v2[i] << "," ;    
            return 0;
}

输出:


5
0,1,2,3,100,
1,2,13,3,4,5,


例:
int main()  {
const int SIZE = 5;
int a[SIZE] = {1,2,3,4,5 }; 
vector<int> v (a,a+5);  //构造函数
try {
v.at(100) = 7;
}
catch( out_of_range e) {
cout << e.what() << endl;
}
cout << v.front() << “,” << v.back() << endl;
v.erase(v.begin());
ostream_iterator<int> output(cout ,“*");
copy (v.begin(),v.end(),output);
v.erase( v.begin(),v.end());  //等效于 v.clear();


if( v.empty ())
cout << "empty" << endl;
v.insert (v.begin(),a,a+SIZE);
copy (v.begin(),v.end(),output);
}  


// 输出:
invalid vector<T> subscript
1,5
2*3*4*5*empty
1*2*3*4*5*

关于 ostream_iterator, istream_iterator的例子
int main()  {
istream_iterator<int> inputInt(cin);
int n1,n2;
n1 = * inputInt; //读入 n1
inputInt ++;   
n2 = * inputInt; //读入 n2
cout << n1 << "," << n2 << endl;
ostream_iterator<int>> outputInt(cout);
* outputInt = n1 + n2;  cout << endl;
int a[5] = { 1,2,3,4,5};
copy(a,a+5,outputInt);  //输出整个数组
            return 0;
}

程序运行后输入 78  90敲回车,则输出结果为:
78,90
168
12345


例';

#include <set>
#include <iostream>
using namespace std;
int main()  {
typedef set<double,less<double> > double_set;
const int SIZE = 5;
double a[SIZE] = {2.1,4.2,9.5,2.1,3.7 };
double_set doubleSet(a,a+SIZE);
ostream_iterator<double> output(cout," ");
cout << "1) ";
copy(doubleSet.begin(),doubleSet.end(),output);
cout << endl;
      pair<double_set::const_iterator, bool> p;
      p = doubleSet.insert(9.5); 
      if( p.second ) 
cout << "2) " << * (p.first)  << " inserted" << endl;
      else
            cout << "2) " << * (p.first)  << " not inserted" << endl;
      return 0; }



输出:
1) 2.1 3.7 4.2 9.5
2) 9.5 not inserted


#include <iostream>
#include <map>
using namespace std;
ostream & operator <<( ostream & o,const pair<  int,double> & p)
{
o << "(" << p.first  << "," << p.second << ")";
return o;
}
int main()  {
typedef map<int,double,less<int> > mmid;
mmid pairs;
cout << "1) " << pairs.count(15) << endl;
pairs.insert(mmid::value_type(15,2.7));
pairs.insert(make_pair(15,99.3));//make_pair生成pair对象
cout << "2) " << pairs.count(15) << endl;
pairs.insert(mmid::value_type(20,9.3));

      mmid::iterator i;
      cout << "3) ";
      for( i = pairs.begin(); i != pairs.end();i ++ )
    cout << * i  << ",";
cout << endl;
cout << "4) ";
int n =  pairs[40];//如果没有关键字为40的元素,则插入一个
for( i = pairs.begin(); i != pairs.end();i ++ )
cout << * i  << ",";
cout << endl;
cout << "5) ";
pairs[15] = 6.28; //把关键字为15的元素值改成6.28
for( i = pairs.begin(); i != pairs.end();i ++ )
cout << * i  << ",";
            return 0;
}



输出:
1) 0
2) 1
3) (15,2.7),(20,9.3),
4) (15,2.7),(20,9.3),(40,0),
5) (15,6.28),(20,9.3),(40,0),


如何用程序用来统计一篇英文文章中单词出现的频率(为简单起见,假定依次从键盘输入该文章) 
       #include <iostream

> #include <map>

using namespace std;

int main() {  

  map<string, int> wordCount;   

 string word;    

while (cin >> word)        

++wordCount[word];       

 for (map<string, int>::iterator it = wordCount.begin(); it !=    wordCount.end(); ++it)  

     cout<<"Word: "<<(*it).first<<" \tCount: "<<(*it).second<<endl;      

  return 0; }



例:

#include <queue>
#include <iostream>
using namespace std;
int main()  {
priority_queue<double> priorities;
priorities.push(3.2);
priorities.push(9.8);
priorities.push(5.4);
while( !priorities.empty() ) {
cout << priorities.top() << " ";    priorities.pop();
}
     return 0;

//输出结果:9.8 5.4 3.2


例:

int main()  {
const int SIZE = 10;
int a1[] = { 2,8,1,50,3,100,8,9,10,2 };
vector<int> v(a1,a1+SIZE);
ostream_iterator<int> output(cout," ");
vector<int>::iterator location;
location = find(v.begin(),v.end(),10);
if( location != v.end()) {
cout << endl << "1) " << location - v.begin();
}
  sort(v.begin(),v.end());
       if( binary_search(v.begin(),v.end(),9)) 
           cout << endl << "3) " << "9 found";
      else
    cout << endl << " 3) " << " 9 not found";       
      return 0;
}

输出:(无sort语句)


1) 8
2) 3
3) 9 not found

输出: (有sort语句)
1) 8
2) 3
3) 9 found






posted @ 2013-10-13 08:40  ZhangAihua  阅读(303)  评论(0编辑  收藏  举报