最近思考到这样一个题目:在STL的set和vector容器里存储了1亿个QQ号,编写函数删除奇数QQ号。git
首先了解一下 set 和 vector 以及其余相似的 STL 容器:github
容器 | 描述 |
---|---|
vector | 向量,一个有着N个或更多连续存储的元素的数组。 |
list | 列表,一个由节点组成的双向链表,每一个节点中包含一个元素。 |
deque | 双队列,一个有着N个或更多连续存储的指向不一样元素的指针组成的数组。 |
set | 集合,一个由节点组成的红/黑树,每一个节点包含一个元素,节点之间以某种做用与元素对的谓词排序,没有两个不一样的元素可以拥有相同的次序。 |
multiset | 多重集合,容许存在两个次序相同的元素的集合。 |
map | 映射,一个由{键 , 值}对组成的集合,以某种做用于键对上的谓词排序,使用pair<键, 值>。 |
multimap | 多重映射,容许键有重复的,即一个键能够有多个对应的值。 |
容器 | vector | deque | list | set/map |
---|---|---|---|---|
插入/删除 | N | N | 常量 | log(N) |
从前面添加 | N | 常量 | 常量 | log(N) |
find(val) | N | N | N | log(N) |
X(N) | 常量 | 常量 | N | N |
指针 | 0 | 1 | 2 | 3 |
这些容器几乎是由其余容器实现的容器,只是对存取元素方面进行了部分的限制。算法
容器 | 描述 |
---|---|
stack | 栈,后进先出的队列。 |
queue | 队列,先进先出。 |
priority_queue | 优先队列,一个队列,其中元素的次序是由做用于所存储值对上的某种谓词决定的,拥有高优先级的元素会先被出队。 |
第一个思路就是使用erase函数一个个去删,(不知道有没有什么更好的方法请在评论里指点一下,谢谢)这里,set和vector的存储方式是不同的。可是它们都提供了一个删除元素的接口erase:数组
// set iterator erase(iterator it); iterator erase(iterator first, iterator last); size_type erase( const Key& key);
// vector , list , deque iterator erase(iterator it); iterator erase(iterator first, iterator last);
了解了这个之后,能发现,算法题中的说存储在set和vector中,其实其内部存储是不同的,删除的实现原理也是不一样的。但均可以用同一个接口erase()去实现!及时这时候添加说还存储在list和deque中,也是可使用的。咱们能够写两个函数去实现这个功能,但因为在两个容器中,而调用的接口又都是同样的,因此天然而然想到可使用模板函数!这是其一。微信
第二,题目中说是QQ号,众所周知,QQ目前已经多达11位了,之后还会更长,因此将QQ号设为整型确定是不合适的了,因此这里须要使用long long 。同时,遍历容器时,确定是要使用迭代器来进行遍历的,这样能保证速度。函数
第三,题目中说一亿个QQ号,目前还不知道这里藏着什么坑,感受是有的,我写的代码反正是死掉了,一亿条,添加和删除的循环都搞死了。还请大神帮忙分析分析!测试
因此基于以上分析,写出如下代码:指针
#include <utility> #include <set> #include <vector> typedef long long dlong; template <typename T> void qq_delete_stl_template(T &t){ typename T::iterator it=t.begin(); //typename用来讲明T::iterator是一个类型, //不然iterator会被认为是T中的一个成员变量 while(it!=t.end()){ //每次删除后都会致使t.end()指向的都是不一样的位置 if((*it)&1){ //奇数 it=t.erase(it); //删除迭代起指向的内容,并返回删除后的下一项内容 }else{ ++it; } } } //调用时应该是: set<dlong> s; //假设s里存有1亿个QQ号 qq_delete_stl_template(s); vector<dlong> v; //假设v里存有1亿个QQ号 qq_delete_stl_template(v);
分析的比较浅显,但愿大神指教!code
完整测试源码对象