learning STL
一、简介
1、STL是C++ 标准程序库的核心,是一个泛型程序库,内部的所有组件由模板构成。
2、容器用来管理某类对象的集合;迭代器,用来在一个对象群集的元素上进行遍历操作,它为所有容器提供了一组很小的公共接口,和一般指针差不多,每种容器都有自己的迭代器;算法,用来处理群集内的元素,包括搜寻,排序,修改,使用这些元素,通过迭代器的协助,我们只需定义一次算法,就可以将它用于任何容器之上,这是因为所有容器的迭代器都提供一致的接口。stl的基本概念就是将数据和操作分离,数据由容器类别加以管理,操作由算法定义,迭代器在两者之间充当粘合剂。stl还提供配接器和仿函数。
二、容器
容器分为序列式容器(vector,deque,list)、关联式容器(set,multiset,map,multimap)。关联容器插入的元素按元素有序排列,关联容器由二叉树实现。
1、vector:将元素置于一个动态数组中,允许随机存取,需包含头文#include<vector>
#include<iostream> #include<vector> using namespace std; int main() { vector<int> coll; for(int i=0;i<6;i++) coll.push_back(i); for(int i=0;i<coll.size();i++) cout<<coll[i]<<" "; cout<<endl; return 0; }
2、deque:它是一个动态数组,可以往两端发展,需包含头文件#include<deque>,可以通过push_front与push_back分别从前端和后端插入元素,使用push_front时,插入顺序与元素排列顺序相反。
#include<iostream> #include<deque> using namespace std; int main() { deque<float> coll; for(int i=0;i<6;i++) coll.push_front(i*1.1); for(int i=0;i<coll.size();i++) cout<<coll[i]<<" "; cout<<endl; return 0; }
3、list:双向链表,不提供随机存取,即不能用下标存取,插入删除非常迅速,需包含头文件#include<list>
#include<iostream> #include<list> using namespace std; int main() { list<char> coll; for(char c='a';c<='z';c++) coll.push_back(c); while(!coll.empty()) { cout<<coll.front()<<" ";//通过coll.front()方法输出第一个元素 coll.pop_front();//删除第一个元素 } cout<<endl; return 0; }
4、set:内部元素按其值自动排序,每个元素只能出现一次,不能重复。(一种特殊的map)
5、mutiset:与set相同,只是可以包含重复元素。
6、map:存储<key,value>对组(键值,实值),每个元素按键值进行排序,每个键只能出现一次,不允许重复。
7、multimap:同map,但允许重复元素,即 multimap可包含多个键值相同的元素。
三、容器配接器
1、stack(LIFO)
2、queue(FIFO)
3、priority queue(元素具有优先级)
四、迭代器
操作符包括:*,++,--,==,!=,=
各种迭代器的接口相同,型别却不同。
成员函数列举如下:
1、begin():返回一个容器迭代器,指向容器起止点。
2、end():返回一个容器迭代器,指向容器结束点。结束点在最后一个元素之后,并不是最后一个元素。
迭代器例1
#include<iostream> #include<list> using namespace std; int main() { list<char> coll; for(char c='a';c<='z';c++) coll.push_back(c); list<char>::const_iterator pos; for(pos=coll.begin();pos!=coll.end();pos++) cout<<*pos<< " "; cout<<endl; return 0; }
任何一种容器都定义有两种迭代器型别。
container::iterator 以读写模式遍历元素
container::const_iterator 只读模式遍历元素
迭代器例2:set+迭代器
#include<iostream> #include<set> using namespace std; int main() { set<int> coll; coll.insert(3); coll.insert(1); coll.insert(5); coll.insert(4); coll.insert(6); coll.insert(2); set<int>::const_iterator pos; for(pos=coll.begin();pos!=coll.end();pos++) cout<<*pos<<" "; cout<<endl; return 0; }
注:此种型别有缺省的排序准则,元素以递增方式排列,如果想定义自己的排序准则,要将排序准则传入template的第二个参数。
即:set<int,greater<int> > 其中 greater<int>为仿函数。
数据保存如图所示:
输出结果为:1 2 3 4 5 6
若想改为multiset,只需将 set<int>改为 multiset<int>,此时若插入两个1,则输出结果为:1 1 2 3 4 5 6
迭代器例3:multimap+迭代器
#include<iostream> #include<map> #include<string> using namespace std; int main() { multimap<int,string> coll; coll.insert(make_pair(5,"tagged")); coll.insert(make_pair(2,"a")); coll.insert(make_pair(1,"this")); coll.insert(make_pair(4,""of)); coll.insert(make_pair(6,"strings")); coll.insert(make_pair(1,"is")); coll.insert(make_pair(3,"multimap")); multimap<int,string>::const_iterator pos; for(pos=coll.begin();pos!=coll.end();pos++) cout<<pos->second<<" ";//等价于cout<<(*pos).second<<" "; cout<<endl; return 0; }
程序输出可能是这样的:this is a multimap of tagged strings
不过由于this 和 is 的键值相同,所以也可能顺序相反。
迭代器例4:map可做关联式数组+迭代器
#include<iostream> #include<map> #include<string> using namespace std; int main() { typedef map<string,float> StringFloatMap; StringFloatMap coll; coll["VAT"]=0.15; coll["Pi"]=3.1415; coll["an arbitrary number"]=4983.223; coll["NULL"]=0; StringFloatMap::iterator pos; for(pos=coll.begin();pos!=coll.end();++pos) cout<<"key:"<<pos->first<<" "<<"value:"<<pos->second<<end; }
map允许使用操作符[]插入元素,例如代码中coll["VAT"]=0.15;
五、算法
算法并非容器类别的成员函数,而是一种搭配迭代器使用的全局函数,这里所阐述的并非OOP思维模式,而是泛型函数编程模式。
为了调用算法,必须包含头文件#include<algorithm>
实例1
#include<iostream> #include<vector> #include<algorithm> using namespace std; int main() { vector<int> coll; vector<int>::iterator pos; coll.push_back(2); coll.push_back(5); coll.push_back(4); coll.push_back(1); coll.push_back(6); coll.push_back(3); pos=min_element(coll.begin(),coll.end()); cout<<"min:"<<*pos<<endl; pos=max_element(coll.begin(),coll.end()); cout<<"max:"<<*pos<<endl; sort(coll.begin(),coll.end()); for(pos=coll.begin();pos!=coll.end();++pos)//测试是否为有序,用迭代器输出 cout<<*pos<<" "; cout<<endl; pos=find(coll.begin(),coll.end(),3); cout<<*pos<<endl;//测试是否找到3 reverse(pos,coll.end()); for(pos=coll.begin();pos!=coll.end();++pos)//测试是否从3开始reverse cout<<*pos<<" "; cout<<endl; return 0; }
参考书籍《C++标准程序库》