最近思考到这样一个题目:在STL的set和vector容器里存储了1亿个QQ号,编写函数删除奇数QQ号。

1. STL容器简介

首先了解一下 set 和 vector 以及其他类似的 STL 容器:

实现描述:

容器 描述
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 优先队列,一个队列,其中元素的次序是由作用于所存储值对上的某种谓词决定的,拥有高优先级的元素会先被出队。

2. 算法解析

第一个思路就是使用erase函数一个个去删,(不知道有没有什么更好的方法请在评论里指点一下,谢谢)这里,set和vector的存储方式是不一样的。但是它们都提供了一个删除元素的接口erase

// set
iterator erase(iterator it);
iterator erase(iterator first, iterator last);
size_type erase( const Key& key);
  • 第一个成员函数:删除 set 中由迭代器 it 指向的元素;
  • 第二个成员函数:删除 set 中区间为 [first , last )中的所有元素;
  • 第一和第二个成员函数都返回一个迭代器,指向紧接着被删除元素的下一个元素,如果没有这样的元素,则迭代器指向 end()。
  • 第三个成员函数:删除 set 中区间为 [lower_bound(key) , upper_bound(key) )中的具有给定排序键key的所有元素,返回删除元素的个数
// vector , list ,  deque
iterator erase(iterator it);
iterator erase(iterator first, iterator last);
  • 第一个成员函数:删除 vector/list/deque 中由迭代器 it 指向的元素;
  • 第二个成员函数:删除 vector/list/deque 中区间为 [first , last )中的所有元素;
  • 第一和第二个成员函数都返回一个迭代器,指向紧接着被删除元素的下一个元素,如果没有这样的元素,则迭代器指向 end()。
  • vector时,删除 N 个元素将导致调用 N 次析构函数以及从删除点至序列末端的每个元素都被赋值一次。由于不需要进行存储空间的重新分配,所以只有从指向第一个被删除元素到序列末端这个区域的迭代器以及引用才会失效。
  • list时,删除N个元素将调用N次析构函数。由于没有进行任何重新分配发生,只有指向被删除对象的迭代器和引用才会变为无效。
  • deque时,删除N个元素将导致N次调用析构函数以及从删除点至序列较近的末端的每个元素都被赋值一次。在序列的两端删除一个元素仅使得原先指向被删除元素的迭代器和引用变得无效,否则,删除一个元素将导致所有的迭代器和引用都变的无效。

了解了这个以后,能发现,算法题中的说存储在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);

分析的比较浅显,希望大神指教!

完整测试源码

附录

STL容器及算法题:删除奇数的QQ号的更多相关文章

  1. 【坐在马桶上看算法】算法4:队列——解密QQ号

            新学期开始了,小哈是小哼的新同桌(小哈是个小美女哦~),小哼向小哈询问QQ号,小哈当然不会直接告诉小哼啦,原因嘛你懂的.所以小哈给了小哼一串加密过的数字,同时小哈也告诉了小哼解密规则. ...

  2. 算法5:队列——解密 QQ 号

    新学期开始了,小哈是小哼的新同桌(小哈是个小美女哦~),小哼向小哈询问 QQ 号,小哈当然不会直接告诉小哼啦,原因嘛你懂的.所以小哈给了小哼一串加密过的数字,同时小哈也告诉了小哼解密规则.规则是这样的 ...

  3. 刷题常用的STL容器总结

    本文归纳总结刷题常用到STL容器以及一些标准算法,主要包括: string.vector.map.pair.unordered_map.set.queue.priority_queue.stack,以 ...

  4. 每天一道算法题(4)——O(1)时间内删除链表节点

    1.思路 假设链表......---A--B--C--D....,要删除B.一般的做法是遍历链表并记录前驱节点,修改指针,时间为O(n).删除节点的实质为更改后驱指针指向.这里,复制C的内容至B(此时 ...

  5. C++进阶 STL(1) 第一天 [容器,算法,迭代器] string容器 vector容器 deque容器

    课程大纲 02实现基本原理 容器,算法,迭代器 教室:容器 人:元素 教室对于楼:容器 序列式容器: 容器元素在容器中的位置是由进入容器的时间和地点来决定 序列式容器 关联式容器: 教室中 按年龄排座 ...

  6. 【pat】C++之刷题常用STL容器整理

    1.vector 动态数组,方便的动态扩容,方便的变量初始化(int类型默认初始化为0,bool默认初始化为false),可以用来实现邻接表(结点数太多的图). 头文件 #include<vec ...

  7. 《STL源码剖析》——第五、六:关联容器与算法

    第五章.关联容器  5.0.关联容器 标准的STL关联式容器分为set(集合)和map(映射表)两大类,以及这两大类的衍生体multiset(多键集合)和multimap(多键映射表).这些容器的底层 ...

  8. STL容器删除元素的陷阱

    今天看Scott Meyers大师的stl的用法,看到了我前段时间犯的一个错误,发现我写的代码和他提到错误代码几乎一模一样,有关stl容器删除元素的问题,错误的代码如下:std::vector< ...

  9. STL容器的遍历删除

    STL容器的遍历删除 今天在对截包程序的HashTable中加入计时机制时,碰到这个问题.对hash_map中的每个项加入时间后,用查询函数遍历hash_map,以删除掉那些在表存留时间比某个阈值长的 ...

随机推荐

  1. vue项目构建过程

    # template 模版项目 > A Vue.js project* 构建过程* 安装过程* 差异点* 打包优化 ## 构建过程```bashbogon:vue-cli caoke$ vue ...

  2. Python中 字符串 转换为 字典

    需求:把以下字符串转换为字典 #字符串 testStr = '{ "pName": "Ceshi", "gender": 1, " ...

  3. Yii1 的数据库操作整理

    1.根据条件查询一个集合 $objectResult=Post::model()->findAll($condition,$params);$objectResult=Post::model() ...

  4. OSG DB的插件地址设置

    今天搞了一整天OSG,结果每次都说could not find plugin,就是说找不到OSG的插件去加载文件,我大概看了下OSG的插件机制,发现他是用插件的形式下去读取文件的 http://blo ...

  5. [TimesTen]TT7001: User authentication failed

    在使用sqldeveloper连接TimesTen一直报[TimesTen][TimesTen 11.2.2.8.0 ODBC Driver][TimesTen]TT7001: User authen ...

  6. PowerDesigner 16.5 安装和卸载教程【含有安装文件】

    1 下载 下载地址:https://pan.baidu.com/s/1kqly0d8qU-QluEagXwh53g 密码:n1a3 下载之后目录结构如下: 2 安装教程 1 安装 1.双击安装文件,如 ...

  7. javascript移动端滑屏事件

    来看看在pc上面的几个事件:onmousedown,onmousemove,onmouseup 我相信大家对这几个事件一定不陌生,第一个onmousedown表示鼠标按下,第二个onmousemove ...

  8. 1.net平台

    .net/dotnet:一般指的是.Net Framework框架,是一种平台,一种技术.   .net Framewoek框架是.net平台不可缺少的一部分,它提供了一个稳定的运行环境来保证.net ...

  9. swagger快速开发

    转载:https://blog.csdn.net/xxoo00xx00/article/details/77163399 swagger 学习笔记 搭建环境: 1,jdk1.8 2,idea 3,sp ...

  10. C#+ObjectArx CAD二次开发(2)

    前面开了一个头,这里添加几个功能的实现, //添加图层 private void LoadLayer() { Document acDoc = Application.DocumentManager. ...