一、STL简介
从根本上说,STL ( Standard Template Library,标准模板库)是一些“容器”的集合,这些“容器”有list,vector,set,map等,STL也是算法和其他一些组件的集合。STL的目的是标准化组件,在C++标准中,STL被组织为下面的17个头文件:<algorithm>、<deque>、<functional>、<iterator>、<array>、<vector>、<list>、<forward_list>、<map>、<unordered_map>、<memory>、<number>、<queue>、<set>、<unordered_set>、<stack>和<utility>。
STL可分为容器(containers)、迭代器(iterators)、空间配置器(allocator)、配接器(adapters)、算法(algorithms)、仿函数(functors)六个部分。
二、常用容器及其用法介绍
1、deque双端队列
deuqe是 一种具有队列和栈的性质的数据结构,看起来比较灵活,但是实际使用却不如栈和队列。
动态数组deque既可以在数组的开头和结尾插入和删除数据,其余操作与vector相似
#include<iostream>
#include<deque>
#include<algorithm>
using namespace std;
int main()
{
deque<int> a;
a.push_back(3);//从后面加入数据
a.push_back(4);
a.push_back(5);
a.push_front(2);//从前面加入数据
a.push_front(1);
a.push_front(0);
for(int i=0;i<a.size();i++)
{
cout<<"第"<<i<<"个元素为"<<a[i]<<endl;
}
a.pop_front();//pop最前的数据
a.pop_back();//pop最后面的一个数据
cout<<"第二次遍历"<<endl;
for(int i=0;i<a.size();i++)
{
cout<<"第"<<i<<"个元素为"<<a[i]<<endl;
}
deque<int>::iterator i;//定义一个迭代器
for(i=a.begin();i<a.end();i++)//使用迭代器进行遍历
{
//使用distance来计算此位置和开始位置的距离来计算下标
//distance在algorithm头文件中
size_t nOffset=distance(a.begin(),i);
cout<<nOffset<<"下标:"<<*i<<endl;
}
}
2、priority_queue优先级队列
如果我们给每个元素都分配一个数字来标记其优先级,不妨设较小的数字具有较高的优先级,这样我们就可以在一个集合中访问优先级最高的元素并对其进行查找和删除操作了。这样,我们就引入了优先级队列 这种数据结构。默认情况下是最大值优先
//优先级队列
#include<iostream>
#include<queue>
#include<deque>
using namespace std;
int main()
{
priority_queue<int> pq;//优先级队列,默认用vector,默认最大值优先级队列
priority_queue<int,deque<int> > pq2;
priority_queue<int,vector<int>,std::greater<int> > pq3;
pq.push(10);
pq.push(15);
pq.push(5);
pq.push(25);
cout<<pq.size()<<endl;
cout<<pq.top()<<endl;
while(!pq.empty())
{
cout<<pq.top()<<" ";
pq.pop();
}
cout<<endl;
cout<<"最小级优先级队列"<<endl;
pq3.push(10);
pq3.push(15);
pq3.push(5);
pq3.push(25);
cout<<"大小"<<pq3.size()<<endl;
cout<<"top"<<pq3.top()<<endl;
while(!pq3.empty())
{
cout<<pq3.top()<<" ";
pq3.pop();
}
cout<<endl;
return 0;
}
3、bitset
bitset除了可以访问指定下标的bit位以外,还可以把它们作为一个整数来进行某些统计
#include<iostream>
#include<algorithm>
#include<string>
#include<bitset>
using namespace std;
int main()
{
// bitset<32> a;//表示a的大小为32为二进制,a中可以32位,全是0
// cout<<a<<endl;
// bitset<16> b(0xffff);
// cout<<b<<endl;
// bitset<32> c(0xffff);
// cout<<c<<endl;
// bitset<32> d(128);;
// cout<<d<<endl;
// string str("1111111000000000100101");
// bitset<32> f(str,str.size()-4);
// cout<<f<<endl;
bitset<32> a(156);
bitset<32> b;
bitset<32> c;
bool is_set=a.any();//检查有误任何一位为1
if(is_set)
{
cout<<"a里至少有1个1"<<endl;
}
else cout<<"a里没有1"<<endl;
size_t bits_set=a.count();
cout<<"a里1的个数"<<bits_set<<endl;
cout<<"a的大小"<<a.size()<<endl;
for(int i=0;i!=32;i=i+2)
{
b.set(i);
}
b.reset(5);
cout<<b<<endl;
b.flip(8);
cout<<b<<endl;
bitset<32> fourbits(14);
cout<<fourbits<<endl;
cout<<"1的个数"<<fourbits.count()<<endl;
cout<<(fourbits & b)<<endl;//位数相同时
}
4、map
Map是无序存储的,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,每个关键字只能出现一次。
而multimap中的一个值可以重复出现多次,这是map与multimap之间的区别
#include<iostream>
#include<map>
#include<string>
using namespace std;
int main()
{
map<int,string> a;
a.insert(pair<int,string>(1000,"one thousand"));
a.insert(map<int,string>::value_type(3,"three"));
a[2]="two";
cout<<a.size()<<endl;
map<int,string>::const_iterator i;
for(i=a.begin();i!=a.end();i++)
{
cout<<"第一个数"<<i->first<<" "<<" ";
cout<<"第二个数"<<i->second.c_str()<<endl;
}
cout<<a[3]<<endl;
if(a.erase(2)>0)
cout<<"删除成功"<<endl;
map<int,string>::iterator l=a.find(3);//迭代器删除
if(l!=a.end())
{
a.erase(l);
cout<<"success"<<endl;
}
multimap<int,string> ma;
ma.insert(pair<int,string>(1000,"one thousand"));
ma.insert(multimap<int,string>::value_type(3,"three"));
cout<<ma.size()<<endl;
multimap<int,string>::const_iterator mi;
for(mi=ma.begin();mi!=ma.end();mi++)
{
cout<<mi->first<<" "<<endl;
cout<<mi->second.c_str()<<endl;
}
multimap<int,string>::const_iterator fi;
fi=ma.find(1000);
if(fi!=ma.end())
{
cout<<fi->first<<"="<<fi->second.c_str()<<endl;
}
else
{
cout<<"没找到"<<endl;
}
ma.erase(ma.lower_bound(1000),ma.upper_bound(1000));//删除从第一个1000到最后一个1000;
}
5、set
set是一个关联容器类型,用于以升序方式存储唯一值。multiset类似于set,但是值不必是唯一的。
#include<iostream>
#include<set>
//set中的值是不允许重复的,而multiset中的值是允许重复的
using namespace std;
template <typename Container>
void Printt(const Container &c)
{
typename Container::const_iterator i=c.begin();
while(i!=c.end())
{
cout<<*i<<" ";
++i;
}
cout<<endl;
}
int main()
{
set<int> a;
multiset<int> ma;
a.insert(60);
a.insert(-1);
a.insert(3000);
cout<<a.count(300)<<endl;//显示a中300值的个数
// set<int>::const_iterator i=a.begin();//利用迭代器进行遍历
// while(i!=a.end())
// {
// cout<<*i<<endl;
// ++i;
// }
Printt(a);
ma.insert(a.begin(),a.end());//向ma中插入数据
ma.insert(3000);
ma.insert(3000);
cout<<ma.count(3000)<<endl;//输出ma中3000的个数
// multiset<int>::const_iterator j=ma.begin();
// while(j!=ma.end())
// {
// cout<<*j<<endl;
// ++j;
// }
Printt(ma);
}
#include<iostream>
#include<set>
using namespace std;
int main()
{
set<int> a;
a.insert(43);
a.insert(78);
a.insert(-1);
a.insert(124);
set<int>::const_iterator i;
for(i=a.begin(); i!=a.end(); i++)
{
cout<<*i<<endl;
}
set<int>::iterator i_found=a.find(7);
if(i_found!=a.end())
{
cout<<"找到了"<<*i_found<<endl;
}
else cout<<"没有找到"<<endl;
multiset<int> ma;
ma.insert(12);
ma.insert(22);
ma.insert(12);
ma.insert(34);
cout<<"显示数据总数"<<ma.size()<<endl;
multiset<int>::const_iterator j;
for(j=ma.begin(); j!=ma.end(); j++)
{
cout<<*j<<endl;
}
cout<<"要删除的数据"<<endl;
int number=0;
cin>>number;
ma.erase(number);//将所有等于number的数都删除
for(j=ma.begin(); j!=ma.end(); j++)
{
cout<<*j<<endl;
}
ma.clear();//将所有的数据清空
}
6、list
定义list序列模板,这是一个序列的链表,常常在任意位置插入和删除元素
三、常见算法
头文件<algorithm>
非变序算法:
计数算法:count、count_if
搜索算法:search、find、find_if、find_first_of。。。
比较算法:euqal、mismatch、lexicographical_compare
变序算法:
删除算法:remove、remove_if、remove_copy
修改算法:for_each、transfrom
排序算法:sort、stable_sort、partial_sort
。。。。。。
1、查找
查找主要包括 find、find_if、search_n、search、find_end、find_first_of、adjacent_find
下面通过例子来进行介绍
#include<iostream>
#include<deque>
#include<functional>
#include<algorithm>
using namespace std;
int main()
{
deque<int> ideq;
for(int i=1;i<=9;i++)
{
ideq.push_back(i);
}
deque<int>::iterator pos;
for(pos=ideq.begin();pos!=ideq.end();pos++)
{
cout<<*pos<<" ";
}
cout<<endl;
pos=search_n(ideq.begin(),ideq.end(),1,3);
if(pos!=ideq.end())
{
cout<<"找到了连续的1个3,"<<distance(ideq.begin(),pos);
}
else cout<<"没有找到"<<endl;
pos=search_n(ideq.begin(),ideq.end(),3,5,greater<int>());
if(pos!=ideq.end())
{
cout<<"找到了";
}
else cout<<"没有找到";
}
#include<iostream>
#include<algorithm>
#include<deque>
#include<vector>
using namespace std;
#include<list>
bool check(int elem,bool even)
{
if(even)
return elem%2==0;
else return elem%2==1;
}
int main()
{
deque<int> a;
list<int> b;
for(int i=0;i<9;i++)
{
a.push_back(i);
}
for(int i=1;i<10;i++)
{
a.push_back(i);
}
deque<int>::iterator i;
for(i=a.begin();i!=a.end();i++)
{
cout<<*i<<" ";
}
cout<<endl;
for(int i=3;i<9;i++)
{
b.push_back(i);
}
list<int>::iterator j;
for(j=b.begin();j!=b.end();j++)
{
cout<<*j<<" ";
}
cout<<endl;
deque<int>::iterator pos;
pos=search(a.begin(),a.end(),b.begin(),b.end());
if(pos!=a.end())
{
cout<<"找到了"<<distance(a.begin(),pos)+1<<endl;
}
else cout<<"没有找到"<<endl;
++pos;
pos=search(pos,a.end(),b.begin(),b.end());
if(pos!=a.end())
{
cout<<"找到了"<<distance(a.begin(),pos)+1<<endl;
}
else cout<<"没有找到"<<endl;
//使用fimd_end去找,则找最后一个
cout<<"使用find_end查找"<<endl;
pos=find_end(a.begin(),a.end(),b.begin(),b.end());
if(pos!=a.end())
{
cout<<"找到了"<<distance(a.begin(),pos)+1<<endl;
}
else cout<<"没有找到"<<endl;
cout<<"使用谓词"<<endl;
bool checkArgs[3]={true,false,true};
pos=search(pos,a.end(),checkArgs,checkArgs+3,check);
if(pos!=a.end())
{
cout<<"找到了"<<distance(a.begin(),pos)+1<<endl;
}
else cout<<"没有找到"<<endl;
}
2、删除性算法
主要有remove、remove_if、remove_copy、remove_copy_if、unique、unique_copy
#include<iostream>
#include<algorithm>
#include<list>
using namespace std;
int main()
{
list<int> ilist;
for(int i=1;i<=6;i++)
{
ilist.push_front(i);
ilist.push_back(i);
}
list<int>::iterator i;
for(i=ilist.begin();i!=ilist.end();i++)
{
cout<<*i<<" ";
}
cout<<endl;
remove(ilist.begin(),ilist.end(),3);//逻辑删除,没有改变个数
for(i=ilist.begin();i!=ilist.end();i++)
{
cout<<*i<<" ";
}
cout<<endl;
list<int>::iterator ends;
ends=remove(ilist.begin(),ilist.end(),3);
for(i=ilist.begin();i!=ends;i++)
{
cout<<*i<<" ";
}
}
#include<iostream>
#include<algorithm>
#include<list>
#include<set>
using namespace std;
int main()
{
list<int> ilist;
for(int i=1;i<=6;i++)
{
ilist.push_back(i);
}
for(int i=1;i<=9;i++)
{
ilist.push_back(i);
}
list<int>::iterator im;
for(im=ilist.begin();im!=ilist.end();im++)
{
cout<<*im<<endl;
}
multiset<int> iset;
remove_copy_if(ilist.begin(),ilist.end(),inserter(iset,iset.end()),bind2nd(less<int>(),4));
multiset<int>::iterator iter;
for(iter=iset.begin();iter!=iset.end();iter++)
{
cout<<*iter<<endl;
}
}
3、修改算法
//for_each()速度快,不灵活
//transform()速度慢,灵活
#include<iostream>
#include<algorithm>
#include<vector>
void square(int &elem)//必须按引用传递
{
elem=elem*elem;
}
int square2(int elem)
{
return elem=elem*elem;
}
using namespace std;
int main()
{
vector<int> a;
vector<int> b;
for(int i=01; i<=9; i++)
{
a.push_back(i);
b.push_back(i);
}
vector<int>::iterator i;
for(i=a.begin(); i!=a.end(); i++)
{
cout<<*i<<endl;
}
for(i=b.begin(); i!=b.end(); i++)
{
cout<<*i<<endl;
}
for_each(a.begin(),a.end(),square);
for(i=a.begin();i!=a.end();i++)
{
cout<<*i<<" ";
}
cout<<endl;
transform(b.begin(),b.end(),b.begin(),square2);
for(i=b.begin(); i!=b.end(); i++)
{
cout<<*i<<endl;
}
}
4、排序
#include<iostream>
#include<algorithm>
#include<deque>
#include<iterator>
using namespace std;
int main()
{
deque<int> ideq;
for(int i=3;i<=7;i++)
{
ideq.push_back(i);
}
for(int i=1;i<=5;i++)
{
ideq.push_back(i);
}
for(int i=5;i<=9;i++)
{
ideq.push_back(i);
}
deque<int>::iterator i;
for(i=ideq.begin();i!=ideq.end();i++)
{
cout<<*i<<" ";
}
cout<<endl;
nth_element(ideq.begin(),ideq.begin()+3,ideq.end());
for(i=ideq.begin();i!=ideq.end();i++)
{
cout<<*i<<" ";
}
cout<<endl;
copy(ideq.begin(),ideq.begin()+4,ostream_iterator<int>(cout," "));
}
#include<iostream>
#include<deque>
#include<functional>
#include<algorithm>
using namespace std;
int main()
{
deque<int> ideq;
for(int i=1;i<=9;i++)
{
ideq.push_back(i);
}
deque<int>::iterator pos;
for(pos=ideq.begin();pos!=ideq.end();pos++)
{
cout<<*pos<<" ";
}
cout<<endl;
pos=search_n(ideq.begin(),ideq.end(),1,3);
if(pos!=ideq.end())
{
cout<<"找到了连续的1个3,"<<distance(ideq.begin(),pos);
}
else cout<<"没有找到"<<endl;
pos=search_n(ideq.begin(),ideq.end(),3,5,greater<int>());
if(pos!=ideq.end())
{
cout<<"找到了";
}
else cout<<"没有找到";
}
5、比较算法
#include<iostream>
#include<algorithm>
#include<vector>
#include<list>
using namespace std;
bool bothEven(int a,int b)
{
if(a%2==b%2)
return 1;
else return 0;
}
int main()
{
vector<int> a;
list<int> b;
for(int i=1;i<=7;i++)
{
a.push_back(i);
}
for(int i=2;i<=9;i++)
{
b.push_back(i);
}
vector<int>::iterator i;
for(i=a.begin();i!=a.end();i++)
{
cout<<*i<<" ";
}
cout<<endl;
list<int>::iterator j;
for(j=b.begin();j!=b.end();j++)
{
cout<<*j<<" ";
}
cout<<endl;
//使用equal进行比较
//形式1
if(equal(a.begin(),a.end(),b.begin()))
{
cout<<"相等"<<endl;
}
else cout<<"不相等"<<endl;
//形式二
if(equal(a.begin(),a.end(),b.begin(),bothEven))
{
cout<<"相等"<<endl;
}
else cout<<"不相等"<<endl;
//找出两个容器中第一个不相等的
pair<vector<int>::iterator,list<int>::iterator> value;
value=mismatch(a.begin(),a.end(),b.begin());
if(value.first==a.end())
{
cout<<"没有找到不相等的数"<<endl;
}
else cout<<"找到了"<<*value.first<<"---"<<*value.second<<endl;
pair<vector<int>::iterator,list<int>::iterator> values;
values=mismatch(a.begin(),a.end(),b.begin(),less_equal<int>());
if(value.first==a.end())
{
cout<<"没有找到不相等的数"<<endl;
}
else cout<<"找到了"<<*value.first<<"---"<<*value.second<<endl;
//区间比较
//lexicographical_compare(a.begin(),a.end(),b.begin(),b.end());
}
6、最大值最小值算法
#include<iostream>
using namespace std;
#include<algorithm>
#include<deque>
bool absLess(int elem1,int elem2)
{
return abs(elem1)<abs(elem2);
}
int main()
{
deque<int> a;
for(int i=2;i<=8;i++)
{
a.push_back(i);
}
for(int i=-3;i<=5;i++)
{
a.push_front(i);
}
deque<int>::iterator ma;
for(ma=a.begin();ma<a.end();ma++)
{
cout<<*ma<<" ";
}
cout<<endl;
deque<int>::iterator result=min_element(a.begin(),a.end());
cout<<"最小值"<<*result<<endl;
cout<<"最大值"<<*max_element(a.begin(),a.end())<<endl;
cout<<"绝对值最小值"<<*min_element(a.begin(),a.end(),absLess);
cout<<"绝对最大值"<<*max_element(a.begin(),a.end(),absLess);
return 0;
}
关于C++标准库里的内容是非常大的,它凝聚了众多人的智慧,我们在使用的时候会基本的几种算法以及容器就可以了。