STL数据库
1.STL概述
①STL是C++标准程序库的核心,深刻影响了标准程序
库的整体结构
②STL由一些可适应不同需求的集合类(collection
class),以及在这些数据集合上操作的算法
(algorithm)构成
③STL内的所有组件都由模板(template)构成,其元
素可以是任意类型
④STL是所有C++编译器和所有操作系统平台都支持的
一种库
2.STL容器的共同能力
①所有容器中存放的都是值而非引用。如果希望存
放的不是副本,容器元素只能是指针。
②所有元素都形成一个次序(order),可以按相同
的次序一次或多次遍历每个元素
3.STL容器元素的条件
①必须能够通过拷贝构造函数进行复制
②必须可以通过赋值运算符完成赋值操作
③必须可以通过析构函数完称销毁动作
④序列式容器元素的默认构造函数必须可用
⑤某些动作必须定义operator ==,例如搜寻操作
⑥关联式容器必须定义出排序准则,默认情况是重载
operator <
对于基本数据类型(int,long,char,double,…)而言,
以上条件总是满足
4.STL容器的共同操作
①初始化(initialization)
产生一个空容器
std::list<int> l;
以另一个容器元素为初值完成初始化
以数组元素为初值完成初始化
std::list<int> l;
…
std::vector<float> c(l.begin(),l.end());
int array[]={2,4,6,1345};
…
std::set<int> c(array,array+sizeof(array)/sizeof(array[0]));
②与大小相关的操作(size operator)
size()-返回当前容器的元素数量
列:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int intArray[] = {1,2,3,4,5,6};
int num = sizeof(intArray);
cout<<num<<endl;//答案为24,因为共有6个整数,每个整数4个字节
int i = sizeof(intArray)/sizeof(int);//得到整型字符数组的元素个数
cout<<i<<endl;
char intArray1[] = {'1','2','3','4','5','6'};
int j=sizeof(intArray1);
cout<<j<<endl; //答案为6,后面没有'\0'
char intArray2[] = "123456";
int k=sizeof(intArray2);
cout<<k<<endl;//共有7个字符,最后一个为'\0'
}
empty()-判断容器是否为空
列:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "abc";
if(s.empty())
{
cout << "yes" << endl;
}
else
{
cout << "no" << endl;
}
return 0;
}
max_size()-返回容器能容纳的最大元素数量
③比较(comparison)
==,!=,<,<=,>,>=
比较操作两端的容器必须属于同一类型
如果两个容器内的所有元素按序相等,那么这两个容
器相等
采用字典式顺序判断某个容器是否小于另一个容器
④赋值(assignment)和交换(swap)
swap用于提高赋值操作效率
⑤与迭代器(iterator)相关的操作
begin()-返回一个迭代器,指向第一个元素
end()-返回一个迭代器,指向最后一个元素之后
rbegin()-返回一个逆向迭代器,指向逆向遍历的第一
个元素
rend()-返回一个逆向迭代器,指向逆向遍历的最后一
个元素之后
⑥元素操作
insert(pos,e)-将元素e的拷贝安插于迭代器pos所指的
位置
erase(beg,end)-移除[beg,end]区间内的所有元素
clear()-移除所有元素
一.半开区间[beg, end)的好处:
1.为遍历元素时循环的结束时机提供了简单的判断依据(只要未到达end(),循环就可以继续)
2.不必对空区间采取特殊处理(空区间的begin()就等于end())
二.所有容器都提供两种迭代器
container::iterator以“读/写”模式遍历元素
container::const_iterator以“只读”模式遍历元素
二.迭代器分类
双向迭代器
可以双向行进,以递增运算前进或以递减运算后退、可以用==和!=比较。
list、set和map提供双向迭代器
列:list<int> l;
for(pos=l.begin();pos!=l.end();++pos{
…
}
随机存取迭代器
除了具备双向迭代器的所有属性,还具备随机访问能力。
可以对迭代器增加或减少一个偏移量、处理迭代器之间的距离或者使用<和>之类的关系运算符比较两个迭代器。
vector、deque和string提供随机存取迭代器
列:vector<int> v;
for(pos=v.begin();pos<v.end();++pos{
…
}
三.STL容器
1.vector
①vector模拟动态数组
vector的元素可以是任意类型T,但必须具备赋值和拷贝
能力(具有public拷贝构造函数和重载的赋值操作符)
②必须包含的头文件#include <vector>
③vector支持随机存取
④vector的大小(size)和容量(capacity)
size返回实际元素个数,capacity返回vector能容纳的元素最大数量。如果插入元素时,元素个数超过capacity,需要重新配置内部存储器。
⑤迭代器持续有效,除非发生以下两种情况:
(1)删除或插入元素
(2)容量变化而引起内存重新分配
2.移除(remove)元素
操作 效果
c.pop_back() 移除最后一个元素但不返回最后一个元素
c.erase(pos) 删除pos位置的元素,返回下一个元素的位置
c.erase(beg,end) 删除区间[beg,end]内所有元素,返回下一个元素的位置
c.clear() 移除所有元素,清空容器
c.resize(num) 将元素数量改为num(增加的元素用defalut构造函数产生,多余的元素被删除)
c.resize(num,e) 将元素数量改为num(增加的元素是e的副本)
列:#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;
}
2.map/multimap
①构造、拷贝和析构
操作 效果
map c 产生空的map
map c1(c2) 产生同类型的c1,并复制c2的所有元素
map c(op) 以op为排序准则产生一个空的map
map c(beg,end) 以区间[beg,end]内的元素产生一个map
map c(beg,end,op) 以op为排序准则,以区间[beg,end]内的元素产生一个map
~ map() 销毁所有元素并释放内存。
其中map可以是下列形式
map<key,value>一个以less(<)为排序准则的map,
map<key,value,op>一个以op为排序准则的map
②特殊搜寻操作
操作 效果
count(key) 返回”键值等于key”的元素个数
find(key) 返回”键值等于key”的第一个元素,找不到返回end
lower_bound(key) 返回”键值大于等于key”的第一个元素
upper_bound(key) 返回”键值大于key”的第一个元素
equal_range(key) 返回”键值等于key”的元素区间
③安插(insert)元素
操作 效果
c.insert(pos,e) 在pos位置为起点插入e的副本,并返回新元
素位置(插入速度取决于pos)
c.insert(e) 插入e的副本,并返回新元素位置
c.insert(beg,end) 将区间[beg,end]内所有元素的副本插入到c中
列:
#include <iostream>
#include <map>
#include <algorithm>
using namespace std;
struct T1{
int v;
bool operator<(const T1&a)const{
return(v<a.v);
}
};
struct T2{
int v;
};
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;
}
ps:
struct cmp
{
const bool operator()(const T1 &a, const T1 &b)
{
return (a.v < b.v);
}
};
优先队列要对元素做比较,然后再进行插入
sort(a, a + 5, cmp());此时由小到大排列
sort(a ,a + len, greater<int>());//内置类型的由大到小排序
sort(a, a + len, less<int>()); //内置类型的由小到大排序
3.set/multiset
①使用平衡二叉树管理元素
集合(Set)是一种包含已排序对象的关联容器。
②必须包含的头文件#include <set>
③map容器是键-值对的集合,好比以人名为键的地址和电
话号码。相反地,set容器只是单纯的键的集合。当我们
想知道某位用户是否存在时,使用set容器是最合适的。
④set中不允许key相同的元素,multiset允许key相同的元素
⑤pair 模板:pair模板可以用于生成 key-value对
列:
#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;
}
//insert函数返回值是一个pair对象, 其first是被插入元素的迭代
//器,second代表是否成功插入了
/*输出:
1) 2.1 3.7 4.2 9.5
2) 9.5 not inserted*/
4.计算
①count:
template<class InIt, class T>
size_t count(InIt first, InIt last, const T& val);
计算[first,last) 中等于val的元素个数
②count:
template<class InIt, class T>
size_t count(InIt first, InIt last, const T& val);
计算[first,last) 中等于val的元素个数
③min_element:
template<class FwdIt>
FwdIt min_element(FwdIt first, FwdIt last);
返回[first,last) 中最小元素的迭代器,以 “< ”作比较器
④max_element:
template<class FwdIt>
FwdIt max_element(FwdIt first, FwdIt last);
返回[first,last) 中最大(不小)元素的迭代器,以 “< ”作比较器
⑤for_each
template<class InIt, class Fun>
Fun for_each(InIt first, InIt last, Fun f);
对[first,last)中的每个元素 e ,执行 f(e) , 要求 f(e)不能改变e
列:
#include <vector>
#include <iostream>
#include <numeric>
#include <list>
#include <algorithm>
using namespace std;
class CLessThen9{
public:
bool operator()(int n){
return n<9;
}
};
void outputSquare(int value)
{ cout<<value*value<<" "; }
int main()
{
const int SIZE = 10;
int a1[] = { 100,2,8,1,50,3,8,9,10,2 };
vector<int>v(a1,a1+SIZE);
ostream_iterator<int>output(cout, " ");
cout<<endl<<"2)";
cout<<count(v.begin(),v.end(),8);
cout<<endl<<"3)";
cout<<count_if(v.begin(),v.end(),CLessThen9());
cout<<endl<<"4)";
cout<<*(min_element(v.begin(),v.end()));
cout<<endl<<"5)";
cout<<*(max_element(v.begin(),v.end()));
cout<<endl<<"7) ";
for_each(v.begin(),v.end(),outputSquare);
}
输出:
2)2
3)6
4)1
5)100
7) 10000 4 64 1 2500 9 64 81 100 4
5.排序和查找算法
①find
template<class InIt, class T>
InIt find(InIt first, InIt last, const T& val);
返回区间 [first,last) 中的迭代器 i ,使得 * i
②find_if
template<class InIt, class Pred>
InIt find_if(InIt first, InIt last, Pred pr);
返回区间 [first,last) 中的迭代器 i, 使得 pr(*i) == true
③binary_search 折半查找,要求容器已经有序且支持随机访
问迭代器,返回是否找到
template<class FwdIt, class T>
bool binary_search(FwdIt first, FwdIt last, const T& val);
上面这个版本,比较两个元素x,y 大小时, 看 x < y
template<class FwdIt, class T, class Pred>
bool binary_search(FwdIt first, FwdIt last, const T& val, Pred pr);
上面这个版本,比较两个元素x,y 大小时, 看 pr(x,y)
④lower_bound:
template<class FwdIt, class T>
FwdIt lower_bound(FwdIt first, FwdIt last, const T& val);
要求[first,last)是有序的,查找大于等于val的最小的位置
⑤upper_bound
template<class FwdIt, class T>
FwdIt upper_bound(FwdIt first, FwdIt last, const T& val);
要求[first,last)是有序的,查找大于val的最小位置
⑥equal_range
template<class FwdIt, class T>
pair<FwdIt, FwdIt> equal_range(FwdIt first, FwdIt last,const T& val);
要求[first,last)是有序的,返回值是一个pair, 假设为 p, 则
[first,p.first) 中的元素都比 val 小[p.second,last)中的所有元素都比 val 大