一、STL概述
STL组件
1,容器(container)—管理某类对象的集合
2,迭代器(iterator)—在对象集合上进行遍历。
3,容器适配器(container adaptor)
<一>STL容器
(一)STL容器类别
1,序列式容器:排列次序取决于插入时机和位置
2,关联式容器:排列顺序取决于特定准则
(二)STL容器的共同能力
1,所有容器中存放的都是值而非引用。如果希望存放的不是副本,容器元素只能是指针。
2,所有元素都形成一个次序,可以按相同的次序一次或多次遍历每个元素。
(三)STL容器元素的所有条件
1,必须能够通过拷贝构造函数进行复制,
2,必须可以通过赋值运算符完成赋值操作,
3,必须可以通过析构函数完成销毁动作,
4,序列式容器元素的默认构造函数必须可用
5,某些动作必须定义重载=,例如搜寻操作
6,关联式容器默认重载<
(四)STL容器的共同操作
1,初始化,产生一个空容器std::list<int>l;
2,以另一个容器元素为初值完成初始化
Std::list<int>l;
Std::vector<float>c(l.begin(),l.end());
3,以数组元素为初值完成初始化
Int array[]={2,4,6,1345}
Std::set<int>c(array,array+sizeof(array)/sizeof(array[0]);
(五)STL容器的共同操作
1,与大小相关的操作
1)sizeof()—返回当前容器元素的数量
2)empty()—判断当前容器是否为空容器
3)max_size()—返回容器能容纳的最大元素的数量
2,与比较相关的操作
1)==,!=,<,<=,>=
2)比较操作两端的数据必须属于同一类型
3)如果两个容器内的元素按序相等,则这两个容器相同
4)采用字典式顺序判断一个容器是否小于另一个容器
3,与赋值有关的操作
1)复制和交换
Swap用于提高赋值操作的效率
4,元素的操作
1)insert(pos,e)—将元素e的拷贝暗查与迭代器pos所指的位置
2)erase(beg,end)—移除(beg,end)之间的元素
3)clear()—移除所有元素
<二>迭代器
(一)作用:可遍历STL容器内全部或部分元素的对象
指出容器中的一个特定位置
1,*:返回当前位置上的元素值,如果该元素有成员,可以通过迭代器operator->取用
2,++:将迭代器前进至下一个元素
3,==和!=:判断两个迭代器是否指向同一个位置
4,==:为迭代器赋值
5,begin():返回一个迭代器,指向第一个元素
6,end():返回一个迭代器,指向最后一个元素之后
注:[begin,end)是半开区间的好处:
1)为遍历元素时循环的结构时机提供了简单的判断依据(只要未到end(),循环就可以继续)
2)不必对空区间采取特殊处理(空区间的begin(),就等于end())
(二)迭代器分类
container::iterator 以读/写模式遍历元素
container::const_iterator 以只读模式遍历元素
1,双向迭代器:可以双向进行,以递增运算前进或以递减运算后退、可以用==和!=比较
List、set和map提供双向迭代器
List<int>l;
For(pos=l.begin();pos!=l.end();pos++)
{}
2,随机存取迭代器
1)除了具备双向迭代器的所有属性,还具备随机访问能力
2)可以对迭代器增加或减少一个偏移量处理迭代器之间的距离,或者使用<>之类的关系运算符比较两个迭代器
3)victor、deque和string提供算法
Vector<int>v;
For(pos=v.begin();pos<v.end();pos++);
{}
二、STL容器
一、vector
<一>
1,vector模拟动态数组
2,vector的元素可以是任意类型T,但必须具备赋值和拷贝能力(具有public拷贝构造函数和重载的赋值操作符)
3,必须包含的头文件#include<vector>
4,vector支持随机存取
5,vector的大小(size)和容量(capacity)
1) Size返回实际元素的个数
2) Capacity返回vector能容纳的元素的最大数量。如果插入元素时,元素个数超过capacity,需要重新配置内部存储器
<二>vector的相关操作
1,vector<T>c 产生空的vector
2,vector<T>c1(c2) 产生同类型的c1,并将复制c2的所有元素
3,vector<T>c(n) 利用类型T的默认构造函数和拷贝构造函数生成一个大小为n的vector
4,vector<T>c(n,e) 产生一个大小为n的vector,每个元素都是e
5,vector<T>c(beg,end) 产生一个vector,以区间[beg,end)为元素初值
6,~vector<T>() 销毁所有元素并释放内存
7,c.size() 返回元素个数
8,c.empty() 判断容器是否为空
9.c.max_size() 返回元素最大数量
10,c.capacity() 返回重新分配空间可容纳的最大元素数量
11,c.reverse(n) 扩大容量为n
12,c1==c2 判断c1是否等于c2(其他的运算符也是这样操作)
13,c1=c2 强c2的全部元素赋值给c1
14,c.assign(n,e) 将元素e的n个拷贝赋值给c
15,c1.swap(c2) 将c1和c2的元素互换
Swap(c1,c2) 全局函数 c1,c2元素互换
16.c.assign(begin(),end()) 将区间begin()和 end()之间的元素都赋值给c
例:std::list<T>l;
Std::vector<T>v;
v.assign(l.begin(),l.end())
17,begin() 返回一个迭代器,指向第一个元素
rbegin() 返回一个逆向迭代器,指向逆向遍历的第一个元素
end() 返回一个迭代器,指向最后一个元素之后
rend() 返回一个逆向迭代器,指向逆向遍历的最后一个元素之后
18,c.insert(pos,e) 在pos位置插入元素e的副本,并返回新元素的位置
19, c.insert(pos,n,e)在pos位置插入n个e的副本
20 c.insert(pos,beg,end)在pos位置从插入区间[beg,end]内所有元素的副本
21,push_back(e)在尾部添加一个元素e的副本
22,c.pop_back() 移除最后一个元素但不返回最后一个元素
23,c.erase(pos) 移除pos位置的元素,返回下一个元素的位置
24,erase(beg,end) 删除beg和end之间所有元素,返回下一个元素的位置
25,c.clear() 删除所有元素,清空容器
Vector应用实例
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(){
vector<int> a;
for(int i = 0; i < 5; ++i){
a.push_back(5 - i);
}
cout << "Size: " << a.size() << endl;
a.pop_back();
a[0] = 1;
cout << "Size: " << a.size() << endl;
for(int i = 0; i < (int)a.size(); ++i){
cout << a[i] << ", " << endl;
}
cout << endl;
sort(a.begin(), a.end());
cout << "Size: " << a.size() << endl;
for(int i = 0; i < (int)a.size(); ++i){
cout << a[i] << ", " << endl;
}
cout << endl;
a.clear();
cout << "Size: " << a.size() << endl;
return 0;
}
<三>map/multimap
1,使用平衡二叉树管理元素
2,元素包含两部分(key,vaule ) key和vaule可以是任意类型
注:key是要存放元素的关键字,vaule是要查找的元素
3,必须包含头文件#include<map>
4,根据元素key自动对元素排序,因此根据元素key对元素定位很快,但根据元素vaule对元素定位很慢,
5,不能直接改变元素的key,可以通过operator[]直接存取元素的值
6,map中不允许key相同的元素,multimap允许key相同的元素
<四>常见的map/multimap中的函数
1,map c 产生空的map
2,map c1(c2) 产生同类型的c1,并复制c2的所有元素
3,map c(op) 以op为排序准则,产生一个空的map
4,map c(beg,end) 以区间元素产生一个空的map
5,map c(beg,end,op) 以op为排序准则,以区间内的元素产生一个空的map
6,~map 销毁所有元素,并释放内存
注:map可以是以下形式
1)map(key,vaule) 一个以less(<)为排序准则的map
2)map(key,vaule,op) 一个以op为排序准则的map
7,c.size() 返回元素个数
8,c.empty()判断容器是否为空
9,c.max_size() 返回元素最大可能数量
10,c1==c2 判断c1是否等于c2(其他运算符用法一样)
11,c1=c2 将c2的元素全部复制给c1
12,count(key) 记录返回满足条件的元素个数
13,find(key) 返回值等于key的第一个元素,找不到则返回end
14,lower_bound(key) 返回满足条件的第一条记录
15,upper_bound(key) 返回满足条件的最后一条记录的下一个位置
16,equal_range(key) 返回值等于key的区间
17,begin() 返回一个双向迭代器,并指向第一个元素
18,end() 返回一个双向迭代器,并指向最后一个元素的下一个位置
注:其他函数用法与vector差不多
例:
1,map应用实例
#include <iostream>
#include <map>
#include <algorithm>
using namespace std;
struct T1{
intv;
bool operator<(const T1 &a)const{
return (v < a.v);
}
};
struct T2{
intv;
};
struct cmp{
const bool operator()(const T2 &a, const T2 &b){
return (a.v < b.v);
}
};
int main(){
map<T1, int>mt1; //example for user-defined class
map<T2, int, cmp>mt2; //example for user-defined class(functor)
map<string, int> m2;
map<string,int>::iterator m2i, p1, p2;
//map<string, int, greater<string> >m2;
//map<string, int, greater<string> >::iterator m2i, p1, p2;
m2["abd"] = 2;
m2["abc"] = 1;
m2["cba"] = 2;
m2.insert(make_pair("aaa", 9));
m2["abf"] = 4;
m2["abe"] = 2;
cout << m2["abc"] << endl;
m2i= m2.find("cba");
if(m2i != m2.end()){
cout << m2i->first << ": " <<m2i->second << endl;
}else{
cout << "find nothing" << endl;
}
cout << "Iterate" << endl;
for(m2i = m2.begin(); m2i != m2.end(); m2i++){
cout << m2i->first << ": " <<m2i->second << endl;
}
return 0;
}
2,multimap应用实例
#include <iostream>
#include <map>
#include <algorithm>
using namespace std;
int main(){
multimap<string, int> mm1;
multimap<string, int>::iterator mm1i, p1, p2;
mm1.insert(make_pair("b", 3));
mm1.insert(make_pair("a", 0));
mm1.insert(make_pair("b", 5));
mm1.insert(make_pair("c", 4));
mm1.insert(make_pair("b", 2));
cout << "Size: " << mm1.size() << endl;
for(mm1i = mm1.begin(); mm1i != mm1.end(); mm1i++){
cout << mm1i->first << ": " <<mm1i->second << endl;
}
cout << "COUNT: " << mm1.count("b")<< endl;
cout << "Bound: " << endl;
p1= mm1.lower_bound("b");
p2= mm1.upper_bound("b");
for(mm1i = p1; mm1i != p2; mm1i++){
cout << mm1i->first << ": " <<mm1i->second << endl;
}
return 0;
}
三、set/multiset
<一>
1,使用平衡二叉树管理元素
集合(set)是一种包含以排序对象的关联容器
2,必须包含头文件#include<set>
Map容器是键-值对的集合,好比以人名为关键字的地址和电话号码,相反的,set容器只是单纯的关键字的集合,当我们想知道某位用户是否存在时,使用set容器是最合适的
3,set容器中不允许key相同的元素
注:set中只存放一个关键字,而multiset中可以存放很多个
<二>常见函数
与multimap中的常见函数类似,,可对比使用
四、pair模板
<一>pair模板可以用于生成key-value对
<二>例题解析
#include <iostream>
#include <set>
#include <algorithm>
using namespace std;
struct T1{
intkey;
intvalue1, value2;
bool operator<(const T1 &b)const{
return (key < b.key);
}
};
struct T2{
intkey;
intv1, v2;
};
struct T2cmp{
bool operator()(const T2 &a, const T2 &b){
return (a.key < b.key);
}
};
int main(){
multiset<T1> s2;
multiset<T2, T2cmp> s3;
#if 1
multiset<string>s1;
multiset<string>::iterator iter1;
#else
multiset<string, greater<string> >s1;
multiset<string, greater<string> >::iterator iter1;
#endif
s1.insert("abc");
s1.insert("abc");
s1.insert("abc");
s1.insert("bca");
s1.insert("aaa");
cout << "ITERATE:" << endl;
for(iter1 = s1.begin(); iter1 != s1.end(); iter1++){
cout << (*iter1) << endl;
}
cout << "FIND:" << endl;
iter1 = s1.find("abc");
if(iter1 != s1.end()) {
cout << *iter1 << endl;
}else{
cout << "NOT FOUND" << endl;
}
cout << "COUNT: " << s1.count("abc")<< endl;
cout << "BOUND: " << endl;
multiset<string>::iterator s1i, p1, p2;
p1= s1.lower_bound("abc");
p2= s1.upper_bound("abc");
for(s1i = p1; s1i != p2; s1i++){
cout << (*s1i) << endl;
}
return 0;
}
五、算法
<一>常用的算法列表
1,count
Template<class init ,class T>
Size_t count(init first,initlast,const&T&val)
计算[first,last]中等于val的元素的个数
count_if
template<class initt,class pred,classDist>
size_t count_if(init first,init last,pred pr);//按条件(predict pr)查找
计算符合pr(e)==true的元素的个数
<二>排序和查找算法
1,find
Template<class init,class T>
Init find(init first,init last,constT&val);
返回区间[first,last]中的迭代器i,使得*i==val;
2,find_if
Template<class init,class Pred>
Init find_if(init first,init last,Pred pr);
返回区间[first,last]中的迭代器i,使得pr(*i)==true
3,binary_search 折半查找,相当于二分查找
4,lower_bound,upper_bound,equal_range
Lower_bound:
Template<classFwdIt,class T>
FwdIt lower-bound(FwdIt first,FFwdItlast,const T&val)
查找大于等于val的最小的位置
5,sort快速排序
六、学习心得
1,学习了STL标准库模板后,我觉得有很多问题的实现变得简单了很多,因为这个标准可模板提供了很多现成的函数,不用我们自己在定义就可以使用,方便了很多,同时也简化了程序,是程序看起来更加的明了
同时,也有很多以前用函数不好解决的问题也能用这个标准库里面的算法函数去解决
2,Vector与map 的关系可以用一本书来形容
1)map相当于是一本书的目录,而vector则是相当于这本书的内容,在multimap中,要查找的元素相当于目录中的章节,元素再向量数值中的具体位置类似于在书中的页数
2)vector直接存放内容,multimap对原始数据进行排序
3)每一种查找方式都要建一个multimap,multimap可以建很多个
4)向量的内容改变时,multimap对象内容也要相应的做出改变