STL面试题总结

  1. STL提供哪六大组件?
    1)container。容器是用来存放数据的各种数据结构,以类模板来实现。STL容器分为2大类,序列式容器和关联式容器。序列式容器有vector,list,deque, stack,queue,priority_queue。关联式容器有map,set,multimap,multiset,unordered_map,unordered_set,unordered_multimap,unordered_multiset .
    2)algorithm。算法是一种函数模板。算法解决问题的数据来自于容器。但是算法看不见容器,对其一无所知。所以他需要的一切信息必须从迭代器中得知,而迭代器必须能够回答算法所有的提问,才能搭配算法的所有操作。
    3)iterator。迭代器是泛化的容器和泛化的算法中的胶着剂。迭代器是一种类模板,一种行为类型智能指针的类模板。通常,各容器都有自己的迭代器类模板,各容器会将其对应的迭代器作为其类型成员,因此说迭代器一般依附于容器之下。迭代器最重要的工作就是对operator* 和 operator->进行重载。
    4)functor。仿函数又名函数对象是一种行为类似函数指针的类模板,仿函数为算法服务,一般作为算法的函数模板中的一个参数。为了能够行为类似函数,其类别中必须自定义function call运算子(operator())
    5)adapter。配接器扮演着轴承,转换器的角色,配接器可以对容器、迭代器、仿函数进行稍作加工,使之有新功能。STL中提供了应用与迭代器上的配接器,包括insert iterator,reverse iterator,iostream iterator。应用在容器上的配接器上有stack,queue。
    6)allocator。SGI STL中的配置器与众不同,SGI使用的特殊空间配置器std::alloc.SGI STL使用2级配置器。第一级配置器配置超过128byte的调用第一级,当配置区块小的时候,调用第二级配置器,使用复扎的内存池的整理模式。
  2. 说说vector底层的存储机制?
    vector其实是一个动态数组,vector中有3个指针分别表示当前容量的“水位”。当向vector中不断的插入元素时,vector会自动成长,扩大其容量为原来的1.5倍或者2倍。成长的过程为:在内存中开辟当前容量1.5倍或2倍的空间,将原来的数据拷贝过来,同时释放原来数据。注意,vector每成长一次,原来的迭代器都会失效。vector删除元素时,其内存空间并不会被释放。若要释放vector的内存,可以申请一个临时vector对象和当前对象进行交换,语法格式为:vector.swap(vec);
  3. 不提供迭代器的容器有哪些?
    stack:只允许取顶部的元素
    queue:只允许取头部的元素
    stack和queue是一种容器adapter,其内部默认藏着一个私有容器deque,stack和queue的一切操作其实都是对deque的一层包装而已。
    heap:每个元素都有排序规则,不提供遍历功能。
  4. vector中的erase和算法中的remove有什么区别?
    erase算法删除了该元素,对该元素进行了析构。而remove只是将要删除的元素放在了vector的末尾,并返回要删除元素的迭代器。算法通过迭代器进行操作,无法知道容器中的细节,无法真正的执行删除操作。
  5. 说说deque的底层机制
    deque是一种双向开口的连续线性空间,可以在头尾两端分别做元素的插入和删除操作。vector其实也可以在头尾进行操作,但是在头部操作时,效率很差。deque系由一段一段的定量连续空间构成,deque最大的任务就是在这些分段的定量连续空间上,维持 其整体连续的假象,并且提供迭代器以供其随机存取。deque采用了一块所谓的map作为主控,map是一小块连续空间,其中每个元素都是指针,指向另一端较大的连续线性空间,称为缓冲区。该缓冲区才是deque的存储空间主体。deque是分段连续的,维持其“整体连续”的假象的任务落在了迭代器上operator++()和operator–()上。deque的迭代器有4个成员。分别是
    T* cur; // 该迭代器所在缓冲区的位置
    T* first; //该迭代器所在缓冲区的头部
    T* last; //该迭代器所在缓冲区的尾部
    T** node;//该指向管控中心,确定该迭代器在管控中心的位置。
    迭代器中map其实是一个行为类似vector的数组。map中存放的元素初始化时一般放在map的中间,以便往2边扩充。
    除外,deque除了维护一个map指针外,还维护了start,finish两个迭代器,分别指向第一缓冲区中第一个元素和最后一个缓冲区中的最后一个元素。
  6. vector、list、deque的比较
    vector:连续存储结构,每个元素在内存中是连续的,支持高效的访问,其迭代器是随机存取迭代器,在尾端插入删除效率高,但是在其他地方插入删除效率低下。
    list:非连续存储结构,每个list中维持一个节点,节点中有前向指针和后向指针,支持前向后向遍历,其迭代器为双向迭代器。list具有高效的插入和删除,不需要vector中的内存拷贝动作。
    deque:双向开口的分段连续线性空间,解决了vector在头部插入效率低下的情况。并且由于deque是分段连续,当需要扩容的时候,只需要在管控中心下对map扩容,随即增加一块缓冲区连接到新增的map上,因此,deque在扩容时不会像vector复制元素和释放原来空间的操作。看似deque集合了vector和list的优点,但是呢,deque带来的副影响是呢要维持一个map管控中心,并且支持随即存取,使用了很复杂的迭代器。deque的迭代器也是随即存取迭代器。
  7. map和set有何区别?
    map和set都是关联式容器,底层实现都是由红黑树实现的。关联式容器的每笔数据都有一个key和value。map和set不同的是set的key值就是value,value的值就是key,且set的key(value)值 不能改变。map的key值和value值是分开的,其key值不允许改变。map和set的key值都不允许重复。set中的元素就是单一的数据,而map中的元素都是以pair的形式存储的。
  8. unordered_map和map的区别在哪里?
    unordered_map的底层实现使用的是hash表,理论上操作的平均复杂度是常数时间,且其中的元素是没有经过排序的。map底层实现使用的是rbtree,理论上平均复杂度是O(logn),其中元素时经过排序的,带来的额外的代价就是存储一个元素改成存储一个红黑是的节点。选用map还是unordered_map,一是看关键字查询操作次数,二是所需要保证的是查询总体时间还是单个查询的时间。如果查询操作次数多,要求其整体效率,那么使用unordered_map,平均处理时间短。如果查询操作次数少,使用 unordered_map可能造成不确定的O(N),那么就使用平均处理时间相对较慢、单次处理时间恒定的map,考虑整体稳定性应该要高于整体效率,因为前提在操作次数较少。如果在一次流程中,使用unordered_map的少数操作产生一个最坏情况O(N),那么unordered_map的优势也因此丧尽了。
  9. 说说迭代器的五种型别,以及迭代器的分类。
    最常用的迭代器相应型别有五种:value_type,difference_type,pointer,reference,iterator_category;
    迭代器可以分为
    input iterator,output iterator,forward iterator,biderectional iterator , random access iterator.
    其中vector 和deque是 random access iterator.
    list是biderectional iterator
    map,set由于是rbtree实现,是biderectional iterator
    unordered_map,unordered_set是forward iterator。
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值