C++容器STL相关面试问题

1、六大组件介绍

容器:数据结构,用来存放数据 算法:常用算法 迭代器:容器和算法之间的胶合剂,“范型指针”
仿函数:一种重载了operator()的类,使得这个类的使用看上去像函数 配置器:为容器分配并管理内存 适配器:修改其他组件接口

2、为何map和set的插入删除效率比用其他序列容器高?

对于关联容器来说,不需要做内存拷贝和内存移动。map和set容器内所有元素都是以节点的方式来存储,其节点结构和链表差不多,指向父节点和子节点

3、红黑树有什么性质?

1.每个节点都是红色或黑色
2.根节点为黑色
3.叶节点为黑色的NULL结点。
4.如果结点为红,其子节点必须为黑
5.任一节点到NULL的任何路径,所含黑结点数必须相同

4、为何map和set的插入删除效率比其他序列高

因为不需要内存拷贝和移动

5、为何map和set每次insert之后,以前保存的iterator不会失效?

因为插入操作只是结点指针换来换去,结点内存没有改变,而iterator就像指向结点的指针,内存没变,指向内存的指针也不会变。

6、当数据元素增多时,(从10000到20000),map、set查找速度会怎样变化?

红黑树用二分查找法,时间复杂度为logN,所以查找次数从log100000=14变为log20000=15,多了1次而已。

7、STL常用的容器有哪些以及各自的特点是什么?

vector:底层数据结构为数组 ,支持快速随机访问。 list:底层数据结构为双向链表,支持快速增删。
deque:底层数据结构为一个中央控制器和多个缓冲区,支持首尾(中间不能)快速增删,也支持随机访问。
stack:底层一般用deque/list实现,封闭头部即可,不用vector的原因应该是容量大小有限制,扩容耗时。
queue:底层一般用deque/list实现,封闭头部即可,不用vector的原因应该是容量大小有限制,扩容耗时。
priority_queue:的底层数据结构一般为vector为底层容器,堆heap为处理规则来管理底层容器实现。
set:底层数据结构为红黑树,有序,不重复。 multiset:底层数据结构为红黑树,有序,可重复。
map:底层数据结构为红黑树,有序,不重复。 multimap:底层数据结构为红黑树,有序,可重复。
unordered_set:底层数据结构为hash表,无序,不重复。
unordered_multiset:底层数据结构为hash表,无序,可重复 。 unordered_map
:底层数据结构为hash表,无序,不重复。 unordered_multimap:底层数据结构为hash表,无序,可重复。

8、为何每次insert之后,以前保存的iterator不会失效?

iterator这里就相当于指向节点的指针,内存没有变,指向内存的指针怎么会失效呢(当然被删除的那个元素本身已经失效了)。相对于vector来说,每一次删除和插入,指针都有可能失效,调用push_back在尾部插入也是如此。因为为了保证内部数据的连续存放,iterator指向的那块内存在删除和插入过程中可能已经被其他内存覆盖或者内存已经被释放了。即使时push_back的时候,容器内部空间可能不够,需要一块新的更大的内存,只有把以前的内存释放,申请新的更大的内存,复制已有的数据元素到新的内存,最后把需要插入的元素放到最后,那么以前的内存指针自然就不可用了。特别时在和find等算法在一起使用的时候,牢记这个原则:不要使用过期的iterator。

9、说说 vector 和 list 的区别

vector底层实现是数组,所以在内存中是连续存放的,随机读取效率高,但插入、删除效率低;list底层实现是双向链表,所以在内存中是任意存放的,插入、删除效率高,但访问元素效率低。
vector在中间节点进行插入、删除会导致内存拷贝,而list不会。
vector一次性分配好内存,不够时才进行2倍扩容;list每次插入新节点都会进行内存申请。

10、deque与vector的区别

vector是单向开口的连续线性空间,deque是双向开口的连续线程空间。
deque没有提供空间保留功能,vector则要提供空间保留功能。 deque也提供随机访问迭代器,但是其迭代器比vector复杂很多

11、vector扩容原理

以原内存空间大小的两倍配置一份新的内存空间,并将原空间数据拷贝过来进行初始化。

12、vector插入删除和list有什么区别

vector插入删除数据,需要对现有数据复制移动,如果vector存储的对象很大或者构造函数很复杂,则开销很大,如果是简单的小数据,效率优于list
list插入和删除数据,需要对现有数据进行遍历,但要在首部插入数据,效率很高。

13、map 和 set 有什么区别

map中的元素是键值对;Set仅是关键字的简单集合; set的迭代器是const的,不允许修改元素的值;
map允许修改value,但不允许修改key; map支持用关键字作下标操作,set不支持下标操作。

14、hash_map和map的区别在哪里?

构造函数。hash_map需要hash函数,等于函数;map只需要比较函数(小于函数).
存储结构。hash_map采用hash表存储,map一般采用 红黑树(RB Tree) 实现。因此其memory数据结构是不一样的。

15、map和unordered_map的区别

map: map内部实现了一个红黑树,红黑树的每一个节点都代表着map的一个元素,因此所有元素都是有序的,对其进行查找、插入、删除得效率都是O(log
n);但是,因为每个结点都需要额外保存数据,所以空间占用率比较高。
unordered_map: unordered_map内部实现了一个哈希表,因此内部元素是无序的,对其进行查找、插入、删除得效率都是O(1);但是建立哈希表比较费时。

16、STL 中迭代器的作用,有指针为何还要迭代器

Iterator(迭代器)模式又称Cursor(游标)模式,用于提供一种方法顺序访问一个聚合对象中各个元素,
而又不需暴露该对象的内部表示。
迭代器不是指针,是类模板,表现的像指针。他只是模拟了指针的一些功能,通过重载了指针的一些操作符,->、*、++、–等,相当于一种智能指针。
迭代器产生原因:Iterator采用的是面向对象的思想,把不同集合类的访问逻辑抽象出来,使得不用暴露集合内部的结构而达到循环遍历集合的效果。

17、auto_ptr可以做vector的元素吗?为什么?

不能。因为STL的标准容器规定它所容纳的元素必须是可以拷贝构造和可被转移赋值的。而auto_ptr不能,可以用shared_ptr智能指针代替。

18、简单说一下next_permutation和partition的实现?

1.next_permutation(下一个排列)   首先,从最尾端开始往前寻找2个相邻元素,令第一个元素为i,第二个元素为I,且满足i< I,找到这样一组相邻元素后,再从尾端开始向前检验,找出第一个大于i的元素j,将i和j对调,再将ii之后的所有元素颠倒排列,此即所求“下一个”排列组合。
2.partion:   令头端迭代器first向尾部移动,尾部迭代器last向头部移动。当first所指的值大于或等于枢轴时就停下来,当last所指的值小于或等于枢轴时也停下来,然后检验两个迭代器是否交错。如果first仍然在last左边,就将连着元素互换,然后各自调整一个位置(向中央逼近),再继续进行相同的行为。如果发现两个迭代器叫错了,表示整个序列已经调整完毕。

19、不允许有遍历行为的容器有哪些?(不提供迭代器)

1.queue ,除了头部外,没有其他方法存取deque的其他元素。
2.stack(底层以deque实现),除了最顶端外,没有任何方法可以存取stack的其他元素。
3.heap,所有元素都必须遵循特别的排序规则,不提供遍历功能。

20、list自带排序函数的排序原理。

将前两个元素合并,再将后两个元素合并,然后合并这两个子序列成4个元素的子序列,重复这一过程,得到8个,16个,…,子序列,最后得到的就是排序后的序列。时间复杂度:O(nlgn)

面试题均取之于网络,如有问题还请各位前辈多多指正。
  • 2
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凉开水白菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值