这段时间开始刷题了,之前在本科的时候学过C++,然而程度不够刷题,需要看看关于STL之类的东西,让代码写起来更容易更简洁。
一、了解是什么是STL
STL是指C++的标准模板库(Standard Template Library),其中封装了一些常用的数据结构及其对应的常用操作算法,使得在实现相同功能的情况下其代码看起来比C简单很多,因为C更偏向底层,而C++因为封装了一些常用东西使得其我们在写代码的过程中可以很方便的调用来编程。
二、STL 六大组件
1.容器(Container)
2.算法(Algorithm)
3.迭代器(Iterator)
4.函数对象,又称仿函数(Function object)
5.适配器(Adaptor)
6.空间配置器(Allocator)
对于我这种使用C++来刷题的屌丝,常用的组件就只有前三种,后三种表示完全没有接触过,因此,博文只会涉及前三种组件的知识。
组成的库来说提供了更好的代码重用机会。在C++标准中,STL被组织为下面的13个头文件:<algorithm>,<functional>,<numeric>, <iterator>,<utility>,<memory>, <vector>,<list>,<stack>,<set>,<queue>,<deque>,<map>
1、容器
刷题中常用的3种容器是vector,set,map,stack,queue
vector
vector<int> vec;
vec.push_back();
vec.pop_back();
vec.size();
vec.resize();
sort(vec.begin(), vec.end());
map
Map中的元素是自动按key升序排序,所以不能对map用sort函数
定义value为Int类型的map,其初始值默认为0,其他类型则没有
map的基本操作函数:
C++ Maps是一种关联式容器,包含“关键字/值”对
begin() 返回指向map头部的迭代器
clear() 删除所有元素
count() 返回指定元素出现的次数,a.count(element),其中,element指的是key而不是value,因此对于map来说,只能是0或者1。
empty() 如果map为空则返回true
end() 返回指向map末尾的迭代器
equal_range() 返回特殊条目的迭代器对
erase() 删除一个元素
find() 查找一个元素
get_allocator() 返回map的配置器
insert() 插入元素
key_comp() 返回比较元素key的函数
lower_bound() 返回键值>=给定元素的第一个位置
max_size() 返回可以容纳的最大元素个数
rbegin() 返回一个指向map尾部的逆向迭代器
rend() 返回一个指向map头部的逆向迭代器
size() 返回map中元素的个数
swap() 交换两个map
upper_bound() 返回键值>给定元素的第一个位置
value_comp() 返回比较元素value的函数
map<char, int>myMap;
if(myMap.find(a[i]) == myMap.end())//哈希表中不含a[i]元素
myMap['a'] = 1
else
myMap['a'] ++;
遍历map中的key和value
map<char,int>::iterator it;
for(it = myMap.begin(); it!=myMap.end(); it++){
cout << it->first << it->second ;
//first代表key,second代表value
}
//map中删除元素
it = myMap.find("aa");
if(it==myMap.end())
cout<<"we do not find aa"<<endl;
else myMap.erase(it); //delete aa;
关于set(找出两个向量中的交集)
将vector中的元素复制到set中之后,set中会按顺序留有vector中不重复的元素
eg:
int arr[5] = {3,2,2,4,3};
set<int> s(arr,arr+5);
set<int>::iterator it;
for(it=s.begin();it!=s.end();it++)
cout<<*it<<endl;//2,3,4
set中插入元素
set<int> s;
s.insert(8);
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
set<int> s(nums1.begin(), nums1.end()), res;
for (auto a : nums2) {
if (s.count(a)) res.insert(a);
}
return vector<int>(res.begin(), res.end());
}
容器方法count的使用:用来查找序列中某个元素的个数
algorithm头文件定义了一个count的函数,其功能类似于find。这个函数使用一对迭代器和一个值做参数,返回这个值出现次数的统计结果。
cout<<count(ivec.begin() , ivec.end() , searchValue)
STL中容器可分为序列式容器和关联式容器,其中,序列式容器的每个元素的位置取决于元素被插入时设置的位置,和元素值本身无关,而,关联式容器的元素位置取决于特定的排序规则,和插入顺序无关。意思就说,序列式容器中每个元素的位置与插入的顺序对应,而关联式容器中元素会根据特定的排序规则对每个元素进行排序,与元素插入的顺序无关。
序列式容器包括:vector、list和deque,而关联式容器有:set、multiset、map和multimap
向量(vector) :连续存储的元素,动态数组
列表(list):由节点组成的双向链表,每个结点包含着一个元素
双队列(deque) 连续存储的指向不同元素的指针所组成的数组
集合(set) 由节点组成的红黑树,每个节点都包含着一个元素,节点之间以某种作用于元素对的谓词排列,没有两个不同的元素能够拥有相同的次序
多重集合(multiset) 允许存在两个次序相等的元素的集合
栈(stack) 后进先出的值的排列
队列(queue) 先进先出的执的排列
优先队列(priority_queue) 元素的次序是由作用于所存储的值对上的某种谓词决定的的一种队列
映射(map) 由{键,值}对组成的集合,以某种作用于键对上的谓词排列
多重映射(multimap) 允许键对有相等的次序的映射
2、算法
算法是用来操作容器中数据的模板函数,它抽象了对数据结构的操作行为。要使用STL中定义的算法,应首先引入头文件。例如STL中的sort()函数可以对容器中的数据进行排序,可以使用find()函数来搜索容器中的某个元素。
<algorithm>
是所有STL头文件中最大的一个(尽管它很好理解),它是由一大堆模版函数组成的,可以认为每个函数在很大程度上都是独立的,其中常用到的功能范围涉及到比较、交换、查找、遍历操作、复制、修改、移除、反转、排序、合并等等。
里面含有大部分算法,包括求最大值,最小值*min_element
min_element(v.begin(),v.end())
max_element(v.begin(),v.end())
<numeric>
体积很小,只包括几个在序列上面进行简单数学运算的模板函数,包括加法和乘法在序列上的一些操作。
`中有个很重要的函数accumulate,累加求和
其中最后一个是初始累加值
int sum = accumulate(vec.begin() , vec.end() , 0);
<functional>
中则定义了一些模板类,用以声明函数对象。
3、迭代器
STL实现要点是将容器和算法分开,使两者彼此独立。迭代器使两个联系起来,迭代器提供访问容器中的方法。迭代器实质上是一种智能指针,它重载了->和*操作符。事实上,C++指针也是一种迭代器。
<utility>
是一个很小的头文件,它包括了贯穿使用在STL中的几个模板的声明,
<iterator>
中提供了迭代器使用的许多方法,而对于<memory>
的描述则十分的困难,它以不同寻常的方式为容器中的元素分配存储空间,同时也为某些算法执行期间产生的临时对象提供机制,<memory>
中的主要部分是模板类allocator,它负责产生所有容器中的默认分配器。
三.STL demo
vector
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main(void){
int a[]={1,3,4,6,8,7};
vector<int> arr(a,a+6);
vector<int> ::iterator begin;
/*Initialize a vector*/
cout<<"Initialize vector arr with a:"<<endl;
for(begin=arr.begin();begin!=arr.end();begin++)
cout<<*begin<<" ";
cout<<endl;
/*Sort the vector*/
cout<<"After arr was sorted:"<<endl;
sort(arr.begin(),arr.end());
for(begin=arr.begin();begin!=arr.end();begin++)
cout<<*begin<<" ";
cout<<endl;
/*pop*/
arr.pop_back();
cout<<"After pop_back:"<<endl;
for(begin=arr.begin();begin!=arr.end();begin++)
cout<<*begin<<" ";
cout<<endl;
/*push*/
arr.push_back(8);
cout<<"After push_back:"<<endl;
for(begin=arr.begin();begin!=arr.end();begin++)
cout<<*begin<<" ";
cout<<endl;
/*search*/
const int FINDNUMBER=4;
cout<<"Find the element which value is 4:"<<endl;
vector<int> ::iterator search=find(arr.begin(),arr.end(),FINDNUMBER);
if(search!=arr.end())
cout<<"Find"<<" "<<*search<<" "<<"SUCCESS"<<endl;
else
cout<<"FAILED"<<endl;
/*clear*/
cout<<"Destroy the vector"<<endl;
arr.clear();
}
deque
#include<iostream>
#include<deque>
#include<algorithm>
using namespace std;
int main(void){
int arr[]={5,8,9,4,6,2};
/*Initialize the queue*/
cout<<"Initialize the queue"<<endl;
deque<int> que(arr,arr+6);
deque<int> ::iterator pos;
/*Traverse the queue*/
cout<<"Traverse the queue"<<endl;
for(pos=que.begin();pos!=que.end();pos++)
cout<<*pos<<" ";
cout<<endl;
/*push_back*/
cout<<"push_back"<<endl;
que.push_back(10);
for(pos=que.begin();pos!=que.end();pos++)
cout<<*pos<<" ";
cout<<endl;
/*push_front*/
cout<<"push_front 5"<<endl;
que.push_front(5);
for(pos=que.begin();pos!=que.end();pos++)
cout<<*pos<<" ";
cout<<endl;
/*pop_front*/
cout<<"pop_front"<<endl;
que.pop_front();
for(pos=que.begin();pos!=que.end();pos++)
cout<<*pos<<" ";
cout<<endl;
/*pop_back*/
cout<<"pop_back"<<endl;
que.pop_back();
for(pos=que.begin();pos!=que.end();pos++)
cout<<*pos<<" ";
cout<<endl;
/*search number 9*/
cout<<"search number 9"<<endl;
deque<int>:: iterator search=find(que.begin(),que.end(),9);
if(search!=que.end())
cout<<"Find"<<" "<<*search<<" "<<"SUCCESS"<<endl;
else
cout<<"FAILED";
}
list
#include<iostream>
#include<list>
#include<algorithm>
using namespace std;
int main(void){
/*Initialize Linklist*/
int arr[]={3,8,9,4,6,2,4,8};
list<int> Linklist(arr,arr+8);
list<int> ::iterator pmove;
/*isEmpty?*/
if(Linklist.empty())
cout<<"Linklist is empty"<<endl;
else
cout<<"Linklist is not empty"<<endl;
/*Traverse*/
cout<<"Traverse Linklist"<<endl;
for(pmove=Linklist.begin();pmove!=Linklist.end();pmove++)
cout<<*pmove<<" ";
cout<<endl;
/*push_back*/
cout<<"Push_back 5"<<endl;
Linklist.push_back(5);
for(pmove=Linklist.begin();pmove!=Linklist.end();pmove++)
cout<<*pmove<<" ";
cout<<endl;
/*find push_front pop_front and pop_back is same with oush_back operation, I dont wanna repeat*/
/*count*/
cout<<"Count"<<endl;
int Count=count(Linklist.begin(),Linklist.end(),4);
cout<<Count;
}
未完待续。。。