C++ STL算法与迭代器面试题

1. STL中常用的算法有哪些?

答案:

  • 查找算法find:查找元素find_if:按条件查找binary_search:二分查找(需有序)lower_bound/upper_bound:查找边界
  • 排序算法sort:快速排序stable_sort:稳定排序partial_sort:部分排序nth_element:第n个元素
  • 修改算法copy:拷贝元素transform:变换元素replace:替换元素remove:删除元素(不真正删除)
  • 数值算法accumulate:累加inner_product:内积partial_sum:部分和

2. 迭代器的分类有哪些?

答案:

  • 输入迭代器(Input Iterator)只读,单向移动支持:++、*、==、!=例如:istream_iterator
  • 输出迭代器(Output Iterator)只写,单向移动支持:++、*例如:ostream_iterator
  • 前向迭代器(Forward Iterator)读写,单向移动支持:++、*、==、!=例如:forward_list的迭代器
  • 双向迭代器(Bidirectional Iterator)读写,双向移动支持:++、--、*、==、!=例如:list、set、map的迭代器
  • 随机访问迭代器(Random Access Iterator)读写,随机访问支持:+、-、[]、<、>等例如:vector、deque的迭代器

3. sort函数的实现原理是什么?

答案:

  • 混合排序算法主要使用快速排序(Quick Sort)数据量小时使用插入排序(Insertion Sort)递归深度过大时使用堆排序(Heap Sort)称为内省排序(Introspective Sort)
  • 时间复杂度平均:O(n log n)最坏:O(n log n)优于纯快速排序的O(n²)最坏情况
  • 稳定性sort是不稳定排序stable_sort是稳定排序
  • 使用要求需要随机访问迭代器元素需要支持<运算符或提供比较函数

4. remove和erase的区别是什么?

答案:

  • removeSTL算法,不真正删除元素将不删除的元素移到前面返回新的逻辑结尾迭代器容器size不变
  • erase容器成员函数,真正删除元素改变容器大小释放内存
  • remove-erase惯用法vec.erase(remove(vec.begin(), vec.end(), value), vec.end());先remove移动元素,再erase删除
  • 为什么这样设计算法不依赖具体容器提高灵活性和通用性可以一次remove多个值,再统一erase

5. lambda表达式在STL中的应用?

答案:

  • 基本语法[捕获列表](参数列表) -> 返回类型 { 函数体 }简化版:[捕获列表](参数列表) { 函数体 }
  • 捕获方式[]:不捕获[=]:值捕获所有[&]:引用捕获所有[x, &y]:x值捕获,y引用捕获
  • STL中的应用sort自定义比较:sort(v.begin(), v.end(), [](int a, int b) { return a > b; });find_if条件查找:find_if(v.begin(), v.end(), [](int x) { return x > 10; });for_each遍历:for_each(v.begin(), v.end(), [](int x) { cout << x; });transform变换:transform(v.begin(), v.end(), v.begin(), [](int x) { return x * 2; });
  • 优势代码简洁,就地定义避免定义额外函数对象可以捕获局部变量

6. 什么是函数对象(仿函数)?

答案:

  • 定义重载了operator()的类对象可以像函数一样调用也叫仿函数(Functor)
  • 优势可以保存状态可以内联优化,性能好可以作为模板参数
  • STL中的函数对象算术:plus、minus、multiplies关系:less、greater、equal_to逻辑:logical_and、logical_or
  • 示例
struct Compare {    bool operator()(int a, int b) const {        return a > b;    }};sort(v.begin(), v.end(), Compare());

7. 什么是适配器(Adapter)?

答案:

  • 容器适配器stack:基于deque或vectorqueue:基于deque或listpriority_queue:基于vector
  • 迭代器适配器reverse_iterator:反向迭代insert_iterator:插入迭代器stream_iterator:流迭代器
  • 函数适配器bind:绑定参数not1/not2:逻辑取反mem_fn:成员函数适配
  • 作用改变接口,提供新功能复用现有组件提高灵活性

8. 如何自定义比较函数?

答案:

  • 函数指针
bool cmp(int a, int b) { return a > b; }sort(v.begin(), v.end(), cmp);
  • 函数对象
struct Cmp {    bool operator()(int a, int b) const { return a > b; }};sort(v.begin(), v.end(), Cmp());
  • lambda表达式
sort(v.begin(), v.end(), [](int a, int b) { return a > b; });
  • 使用场景sort、stable_sort排序priority_queue、set、map的比较find_if、count_if等条件算法

9. STL中的空间配置器是什么?

答案:

  • 作用负责内存分配和释放对象构造和析构隐藏内存管理细节
  • 两级配置器第一级:大于128字节,直接malloc/free第二级:小于128字节,使用内存池
  • 内存池优势减少malloc/free调用减少内存碎片提高分配效率
  • 自定义配置器可以自定义内存分配策略用于特殊内存管理需求

10. 如何遍历和修改容器?

答案:

  • 传统for循环
for (size_t i = 0; i < vec.size(); ++i) {    vec[i] *= 2;}
  • 迭代器
for (auto it = vec.begin(); it != vec.end(); ++it) {    *it *= 2;}
  • 范围for(C++11)
for (auto& elem : vec) {    elem *= 2;}
  • 算法
for_each(vec.begin(), vec.end(), [](int& x) { x *= 2; });transform(vec.begin(), vec.end(), vec.begin(), [](int x) { return x * 2; });
  • 注意事项修改时使用引用避免在遍历时改变容器大小注意迭代器失效
全部评论

相关推荐

昨天 16:14
武汉大学 Java
1.&nbsp;问一下本科经历2.&nbsp;介绍一下你第一个项目3.&nbsp;DDD分层架构比传统的MVC有哪些好处?4.&nbsp;你设计的业务分配的算法介绍一下?5.&nbsp;算法有哪些优化思路?6.&nbsp;动态标签列设计怎么思考的?7.&nbsp;数据量有多大?8.&nbsp;数据量很大的话,数据存储怎么优化?9.&nbsp;如何保证缓存和数据库之间的数据一致性?10.&nbsp;相对于你这个项目用哪种方案?11.&nbsp;项目中遇到的最大的困难是什么?12.&nbsp;介绍一下第二个项目13.&nbsp;模型分析diff的上下文怎么考虑?14.&nbsp;如果diff的关联的上下文很长超过token,你会怎么办?15.&nbsp;你想的这种方案,最后输入给模型的prompt是什么?16.&nbsp;对于大模型的其他组件如RAG和skills有了解吗?17.&nbsp;那你有想过把代码拆分成一些知识库放在rag里面吗?18.&nbsp;有对比过其他模型的分析效果吗?19.&nbsp;golang有了解吗?20.&nbsp;HashMap的底层结构21.&nbsp;为什么要用红黑树?22.&nbsp;红黑树增删的时间复杂度?23.&nbsp;MySQL事务隔离级别24.&nbsp;MVCC实现原理25.&nbsp;手撕算法:lc402&nbsp;移掉k位数字&nbsp;-&gt;&nbsp;没想到单调栈,暴力枚举了QAQ反问面试官之后,感觉我的缺点主要在于项目太过于玩具了,对于高并发什么的思考处于比较浅的地步,还有就是code-review对于call&nbsp;graph还有一些成熟的方案不怎么了解过,相当于纯demo,面过几场才知道QAQ,估计是没啥希望了,继续沉淀了噶人们
查看25道真题和解析
点赞 评论 收藏
分享
02-07 12:06
已编辑
华侨大学 测试开发
最近看到很多&nbsp;92&nbsp;的,甚至是硕士,开始往测开赛道卷,说实话有点看不懂。先把话说清楚,大厂里的测开,绝大多数时间干的还是测试的活,只是写点自动化脚本、维护测试平台、接接流水线,真正像开发一样做系统、做架构、做核心平台的测开少得可怜,基本都集中在核心提效组,而且人很少,外面进去的大概率轮不到你,我想真正干过人都清楚。很多人被洗脑了,以为测开也是开,和后端差不多,只是更简单、更轻松、还高薪。现实情况是,测开和开发的职业路径完全不一样。开发的核心是业务和系统能力,测开的核心是稳定性和覆盖率,前者是往上走,后者天花板非常明显。你可以见到很多开发转测开,但你很少见到干了几年测开还能顺利转回开发的。更现实一点说,92&nbsp;的高学历如果拿来做测开,大部分时间就是在做重复性很强的杂活,这种工作对个人能力的放大效应非常弱。三年下来,你和一个双非的,甚至本科的测开差距不会太大,但你和同龄的后端、平台开发差距会非常明显。这不是努不努力的问题,是赛道问题。所谓测开简单高薪,本质上是把极少数核心测开的上限,当成了整个岗位的常态来宣传。那些工资高、技术强的测开,本身就是开发水平,只是挂了个测开的名。普通人进去,99%&nbsp;做的都是项目兜底型工作,而不是你想象中的平台开发。测开不是不能做,但它绝对不是开发的平替,也不是性价比最优解。如果你是真的不想做开发,追求稳定,那测开没问题。但如果你只是觉得测开比后端容易,还能进大厂,那我劝你冷静一点,这只是在用短期安全感换长期天花板。有92的学历,如果你连测开这些重复性工作都能心甘情愿接受,那你把时间精力用在真正的开发、系统、业务深度上,回报大概率比卷测开要高得多。想清楚再下场,别被岗位名和话术带偏了,就算去个前端客户端也是随便占坑的,测开是一个坑位很少赛道,反而大面积学历下放,不用想也能知道会是什么结果,我想各位在JAVA那里已经看到了
小浪_Coding:工作只是谋生的手段 而不是相互比较和歧视
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务