本文适用于STL的快速学习。希望通过最少的介绍,能够帮助迅速理解和掌握STL基本的用法。适用于对算法感兴趣却又无太多精力从事算法类竞赛的同学,本文介绍的方法都是在算法题中频率极高的方法,并抛弃一些效率极高但使用并不方便的代码模式。通过做leetcode,hihocoder的经验,本文中的函数可以满足95%以上的题目对STL的要求。
如果是长期从事C++开发类工作或者参加ACM,编程之美,百度之星类竞赛,本文并不合适。在这推荐《STL源码剖析》简体中文版。
注意事项:
1.头文件全部即为该模板类的名字,比如#include <vector>,额外注意的是需要有#include <algorithm>头文件,因为有很多公用函数在此类中
2.获取长度全部为size()函数,比如v.size(); s.size()等。后面文中不再介绍
3,基本的操作可以理解为增加,遍历和删除,介绍时按照这个顺序给予介绍;函数则从易到难。对于经常组合的方法,会放一起以代码片形式介绍
4.迭代器即为模板类的指针,效率高,但是使用不如直接遍历访问方便。如果非必要,作为补充介绍,该部分不加粗
5.为方便起见,所以数据类型都用int。模板类顺序按照笔者使用的频率介绍
一.vector
vector<int>v; 定义
v.push_back(x); 尾部插入元素
v[i]; 获取i位置的元素,修改i位置的元素都可以。和数组使用一样
v.pop_back(); 删除最后一个元素
v.insert(v.begin()+i,x); 在第i个下标处加入元素x
v.erase(v.begin()+ i); 同理,删除第i个下标处的元素
for(inti=0;i<v.size();i++) cout<<v[i]; 最方便的遍历
sort(v.begin(),v.end()); 从小到大排序,效率比手写的排序高很多
reverse(v.begin(),v.end()); 如果想从大到写排序,则在sort基础上需要逆制,比sort加参数效率高
说明:以上的介绍基本都使用了最简单的实现,包括增加,遍历和删除,排序,指定位置的增加和删除。这里唯一要注意的是删除时下标的变化,根据经验,一般情况下遇到erase删除的bug在算法中还是非常少见,这里在用下标遍历时可以增加回退和边界判断,比用迭代器删除方便好用,缺点是效率不如迭代器。下面最后介绍下迭代器的访问
for(vector<int>::iteratori = v.begin();i!=v.end();i++) cout<<*i;
这里可以看出来,v.begin()和v.end()就是返回指向头部和尾部的指针,这个地方需要理解,因为后面其他的类模板中也会用到
vector是介绍最多,应用最广泛的。后面的类型函数会更少,而且会有非常方便的方法
二.stack
stack<int> s; 定义栈
s.push(x); 插入数据
while(!s.empty()) { //判断是否为空
cout<<s.top(); //返回栈顶元素
s.pop(); //弹出栈顶元素,和s.top()基本是连用的
}
说明:栈的函数需要掌握非常少,因为在算法题中,一般是运用栈和队列的特性解决问题。所以只需要掌握出栈和入栈的方法即可
三.queue
queue<int> q;
q.push(x);
while(!q.empty()) {
cout<<q.front();
q.pop();
}
说明:和栈基本一模一样,就不单独介绍了。唯一的区别就是出队列时候要用q.front()。队列还有一些其他的方法,包括可以获取尾部元素,但无需掌握。在算法题中一定是运用队列特性去解决问题
四.map<key, value>
map<int,int> m; 定义
m[key] = value; 赋值
map<int,int>::iterator mi = m.find(key); //通过key查找,返回迭代器
if(mi != m.end()) { //条件不成立则存在该key,反之则不存在该key
cout<<mi->second; //有first和second属性,value是second属性
}
m.erase(key); 删除key
说明:map要稍微复杂一点,一定要注意以下两点:
1.查找时不能find后直接访问,必须判断是否存在。否则不存在情况下会出bug;查找后输出value则需要用mi的second属性,first属性则为key。可以参照pair
2.STL中map属于无覆盖情形,对于某个已插入key,改变value必须先查找,删除后在重新插入。这里广泛应用于统计数目等
掌握已经几个函数,map就能流畅的使用解决问题了。这里还是要提醒一定注意以上两点,因为这里不太符合主流的hash表的设计
五.set
set<int> s; 定义
s.insert(x); 插入数据
s.count(x); 统计数目,返回值为0则不存在,1为存在,非常实用的函数
s.erase(s.find(x)); 删除元素x
说明:set中唯一要记住的就是count函数,这个函数能够直接判断是否存在,而没有使用迭代器。非常方便,上面3个函数基本可以解决使用到set的所有算法题,还有size()。去重利器。