STL标准库面试题(转)
一、vector的底层(存储)机制
二、vector的自增长机制
三、list的底层(存储)机制
四、什么情况下用vector,什么情况下用list
五、list自带排序函数的排序原理
六、deque的底层机制
七、deque与vector的区别
八、map底层机制,查找复杂度,能不能边遍历边插入
九、vector插入删除和list有什么区别
十、hashtable如何避免地址冲突
十一、hashtable、hash_set、hash_map的区别
十二、hash_map与map的区别、什么时候用它们两个?
十三、红黑树有什么性质?
十四、map和set的3个问题
十五、为什么vector插入操作可能导致迭代器失效
十六、hashtable和hashmap的区别
十七、STL底层数据结构实现
十八、STL提供哪六大组件?
十九、auto_ptr可以做vector的元素吗?为什么?
二十、简单说一下next_permutation和partition的实现?
二十一、不允许有遍历行为的容器有哪些?(不提供迭代器)
一、vector的底层(存储)机制
vector就是一个动态数组,里面有一个指针指向一片连续的内存空间,当空间不够装下数据时,会自动申请另一片更大的空间(一般是增加当前容量的50%或100%),然后把原来的数据拷贝过去,接着释放原来的那片空间;当释放或者删除里面的数据时,其存储空间不释放,仅仅是清空了里面的数据。
二、vector的自增长机制
当已经分配的空间不够装下数据时,分配双倍于当前容量的存储区,把当前的值拷贝到新分配的内存中,并释放原来的内存。
对vector的任何操作,一旦引起空间重新配置,指向原vector的所有迭代器就都失效了。
三、list的底层(存储)机制
以结点为单位存储数据,结点的地址在内存中不一定连续,每次插入或者删除一个元素,就配置或者释放一个元素空间。
四、什么情况下用vector,什么情况下用list
vector可以随机存储元素(即可以通过公式直接计算出元素地址,而不需要挨个查找),但是非尾部插入删除数据时,效率很低,适合对象简单,对象数量变化不大,随机访问频繁。
list不支持随机存储,适用于对象大,对象数量变化频繁,插入和删除频繁。
五、list自带排序函数的排序原理
将前2个元素合并,再将后2个元素合并,然后合并这2个子序列成为4个元素序列的子序列,重复这一过程,得到8个,16个,,,,子序列,最后得到的就是排序后的序列。
时间复杂度O(log n)
六、deque的底层机制
deque动态地以分段连续空间组合而成,随时可以增加一段新的连续空间并链接起来,不提供空间保留功能。
注意:除非必要,我们尽可能选择使用vector而非deque,因为deque的迭代器比vector迭代器复杂很多。对duque的排序,为了提高效率,可先将deque复制到一个vector上排序,然后再复制到deque。
deque采用一块map(不是STL的map容器)作为主控,其为一小块连续空间,其中每个元素都是指针,指向另一段较大的连续空间(缓冲区)。
deque的迭代器包含4个内容:
1)cur:迭代器当前所指元素
2)first:此迭代器所指的缓冲区的头。
3)last:缓冲区尾。
4)node:指向管控中心。
七、deque与vector的区别
1.vector是单向开口的连续线性空间,deque是双向开口的连续线程空间。
2.deque没有提供空间保留功能,vector则要提供空间保留功能。
3.deque也提供随机访问迭代器,但是其迭代器比vector复杂很多
八、map底层机制,查找复杂度,能不能边遍历边插入
红黑树,自平衡的二叉搜索树。自动排序效果不错。
通过map的迭代器不能修改键值,只能修改其实值。
查找复杂度:O(logN)
不可以,map不像vector,它在容器进行erase操作后不会返回后一个元素的迭代器,不能遍历第往后插删。
九、vector插入删除和list有什么区别
vector插入删除数据,需要对现有数据复制移动,如果vector存储的对象很大或者构造函数很复杂,则开销很大,如果是简单的小数据,效率优于list
list插入和删除数据,需要对现有数据进行遍历,但要在首部插入数据,效率很高。
十、hashtable如何避免地址冲突
1.线性探测:hash函数计算某个元素的插入位置后,如果该位置的空间已经被占用,则继续向下寻找,直到找到一个可用空间为止。
2.二次探测:如果计算的位置被占用,就依次尝试H+1^2,H+2^2 等
3.开链:每一个表格元素中维护一个list,在那个list中执行插入、删除
十一、hashtable、hash_set、hash_map的区别
hash_set以hashtable为底层,不具有排序功能,能快速查找,其键值就是实值。(set以红黑树为底层,具有排序功能)
hash_map以hashtable为底层,没有自动排序功能,能快速查找,每一个元素同时拥有一个实值和键值。(map以红黑树为底层,有排序功能)
十二、hash_map与map的区别、什么时候用它们两个?
构造函数:hash_map需要hash function 和等于函数,而 map需要比较函数(大小或小于)
存储结构:hash_map以hashtable为底层,而map以红黑树为底层。
总的来说,hash_map查找速度比map快,而且查找速度基本和数据量大小无关,属于常数级别。而map的查找速度是logN级别。但不一定常数就比log小,而且hash_map还有hash function耗时。
如果考虑效率,特别当元素达到一定数量级时,用hash_map
考虑内存,或者元素数量较少时,用map
选用map还是hash_map,关键是看关键字查询操作次数,以及你所需要保证的是查询总体时间还是单个查询的时间。如果是要很多次操作,要求其整体效率,那么使用hash_map,平均处理时间短。如果是少数次的操作,使用 hash_map可能造成不确定的O(N),那么使用平均处理时间相对较慢、单次处理时间恒定的map,考虑整体稳定性应该要高于整体效率,因为前提在操作次数较少。如果在一次流程中,使用hash_map的少数操作产生一个最坏情况O(N),那么hash_map的优势也因此丧尽了。
十三、红黑树有什么性质?
1.每个节点都是红色或黑色
2.根节点为黑色
3.叶节点为黑色的NULL结点。
4.如果结点为红,其子节点必须为黑
5.任一节点到NULL的任何路径,所含黑结点数必须相同
十四、map和set的3个问题
1.为何map和set的插入删除效率比其他序列高
因为不需要内存拷贝和移动
2.为何map和set每次insert之后,以前保存的iterator不会失效?
因为插入操作只是结点指针换来换去,结点内存没有改变,而iterator就像指向结点的指针,内存没变,指向内存的指针也不会变。
3.当数据元素增多时,(从10000到20000),map、set查找速度会怎样变化?
红黑树用二分查找法,时间复杂度为logN,所以查找次数从log100000=14变为log20000=15,多了1次而已。
十五、为什么vector插入操作可能导致迭代器失效
vector动态增加大小时,并不是在原空间后增加新的空间,而是以原大小的两倍在另外配置一个较大的新空间,然后将内容拷贝过来,并释放原来的空间,由于操作改变了空间,所以迭代器失效。
理论会失效,理论上每次insert或者erase之后,所有的迭代器就重新计算的,所以都可以看做是失效的,原则上就是不能使用过期的内存。
但vector一般底层是用数组实现的,仔细考虑数组的特性,得出结论:
1.insert时,假设insert位置为p,分2种情况:
a)容器还有空余空间,不重新分配内存,p前的迭代器有效,p后的失效。
b)重分内存,p之后的迭代器失效
2.erase时,假设erase位置为p,则p之前的迭代器都有效,并且p指向下一个元素位置,(如果之前p在尾巴上,则p指向无效尾end),p之后的迭代器都无效。
十六、hashtable和hashmap的区别
hashmap以hashtable为底层。有以下不同:
1.hashtable是Dictionary的子类,而hashmap是Map接口的一个实现类
2.hashtable中的方法是同步的,而hashmap的方法不同步
十七、STL底层数据结构实现
1.vector:数组,支持快速随机访问
2:list 双向链表,支持快速增删
3.deque:一个中央控制器和多个缓冲区,支持首尾(中间不能)快速增删,支持随机访问
4.stack:底层用deque或者list实现,不用vector的原因是扩容耗时
5:queue 底层用deque或者list实现,不用vector的原因是扩容耗时
6:priority_queue:一般以vector为底层容器,heap为处理规则来管理底层容器实现
7:set 红黑树 有序,不重复
8:multiset 红黑树 有序,可重复
9:map 红黑树 有序,不重复
10:multimpap 红黑树 有序,可重复
11:hash_set hash表 无序,不重复
12:hash_map hash表 ,无序,不重复
13:hashtable 底层结构为vector
十八、STL提供哪六大组件?
1.容器
就是各种数据结构
序列式容器:array、vector、heap、priority_queue、list、slist、deque、stack、queue
关联式容器:set、map、multiset、multimap、hashtable、hash_set、hash_map、hash_multiset、hash_multimap
2.算法
各种常见算法:sort、search、copy、erase等,值得学习的有,sort、next_permutation、partition、merge sort 等
3.迭代器
扮演容器与算法之间的胶合剂,是所谓的“泛型指针”。共有五种类型,从实现角度看,迭代器是一种将operator*,operator->,operator++,operator–等指针相关操作予以重载的class template.所有的STL容器多附带有自己专属的迭代器。只有容器设计者才知道如何设计迭代器,源生指针也是一种迭代器。是设计模式中的一种。
4.仿函数
行为类函数,可作为算法的某种策略,从实现角度看,仿函数是一种重载了operator()的class或class template。一般函数指针可视为狭义的仿函数。
5.配接器
一种用来修饰容器或者仿函数或迭代器接口的东西。比如queue和stack,看着像容器,其实就是deque包了一层皮。
6.配置器
复制空间配置与管理,从实现角度看,配置器就是实现了动态空间配置、空间管理、空间释放的classtemplate。
十九、auto_ptr可以做vector的元素吗?为什么?
不能。因为STL的标准容器规定它所容纳的元素必须是可以拷贝构造和可被转移赋值的。而auto_ptr不能,可以用shared_ptr智能指针代替。
二十、简单说一下next_permutation和partition的实现?
1.next_permutation(下一个排列)
首先,从最尾端开始往前寻找2个相邻元素,令第一个元素为i,第二个元素为I,且满足i< I,找到这样一组相邻元素后,再从尾端开始向前检验,找出第一个大于i的元素j,将i和j对调,再将ii之后的所有元素颠倒排列,此即所求“下一个”排列组合。
2.partion:
令头端迭代器first向尾部移动,尾部迭代器last向头部移动。当first所指的值大于或等于枢轴时就停下来,当last所指的值小于或等于枢轴时也停下来,然后检验两个迭代器是否交错。如果first仍然在last左边,就将连着元素互换,然后各自调整一个位置(向中央逼近),再继续进行相同的行为。如果发现两个迭代器叫错了,表示整个序列已经调整完毕。
二十一、不允许有遍历行为的容器有哪些?(不提供迭代器)
1.queue ,除了头部外,没有其他方法存取deque的其他元素。
2.stack(底层以deque实现),除了最顶端外,没有任何方法可以存取stack的其他元素。
3.heap,所有元素都必须遵循特别的排序规则,不提供遍历功能。
STL标准库面试题(转)的更多相关文章
- STL笔试面试题总结(干货)(转)
STL笔试面试题总结 一.STL有哪些组件? STL提供六大组件彼此此可以组合套用: 1.容器容器就是各种数据结构,我就不多说,看看下面这张图回忆一下就好了,从实现角度看,STL容器是一种class ...
- 爆牙齿的 Web 标准面试题 【转藏】
<!DOCTYPE html> <html lang="zh-CN"><head> <meta http-equiv="cont ...
- SQL数据库面试题
SQL数据库面试题 1.SQL SREVER中,向一个表中插入了新数据,如何快捷的得到自增量字段的当前值 这种情况其实我们经常用到,比如我们新建了一个用户,建立完用户后我们希望马上得到这个新用户的ID ...
- C++ Templates STL标准模板库的基本概念
STL标准库包括几个重要的组件:容器.迭代器和算法.迭代器iterator,用来在一个对象群集的元素上进行遍历操作.这个对象群集或许是一个容器,或许是容器的一部分.迭代器的主要好处是,为所有的容器提供 ...
- STL标准库-算法-常用算法
技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性 介绍11种STL标准库的算法,从这11种算法中总结一下算法的基本使用 1.accumulate() 累加 2.for_each( ...
- STL标准库-容器-set与multiset
技术在于交流.沟通,转载请注明出处并保持作品的完整性. set与multiset关联容器 结构如下 set是一种关联容器,key即value,value即key.它是自动排序,排序特点依据key se ...
- STL标准库-容器-deque
技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性. deque双向开口可进可出的容器 我们知道连续内存的容器不能随意扩充,因为这样容易扩充别人那去 deque却可以,它创造了内存 ...
- STL标准库-容器-vector
技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性. 向量容器vector是一个动态数组,内存连续,它是动态分配内存,且每次扩张的原来的二倍. 他的结构如下 一 定义 vector ...
- C++ STL标准入门
C++:STL标准入门汇总 第一部分:(参考百度百科) 一.STL简介 STL(Standard Template Library,标准模板库)是惠普实验室开发的一系列软件的统称.它是由Alexand ...
随机推荐
- 戏说前端之CSS编码规范
前言 项目启动时 css 应该注意哪些问题 文件名规范 文件名建议用小写字母加中横线的方式.为什么呢?因为这样可读性比较强,看起来比较清爽,像链接也是用这样的方式,例如 // 地址: github的地 ...
- 聊聊GIS数据的四个分层与GIS服务
本篇不讨论矢量栅格数据的结构,也不讨论矢量与栅格的区别(即设定读者有这方面的基础). 版权声明:原创.博客园/B站/小专栏/知乎/CSDN @秋意正寒 转载请标注原地址并声明转载: https://w ...
- Integer使用==做判断遇到的问题
问题: 最近使用Integer类型的数据做判断时,遇到了一个神奇的问题. 如: Integer a=223; Integer b=223; 这样使用==做判断,得到的结果是 false 原因: 后来查 ...
- gcc 将两个文件合成一个文件(c)
一个文件是: 一个文件是: 两个文件的作用是输出一段文字,其中一个文件调用了另一个文件 gcc 命令为: -c 生成了object 文件,-o 生成了可执行文件,并且合成.
- 关于GC(垃圾回收)
当我用new创建一个对象时,当可分配的内存不足GC就会去回收未使用的对象,但是GC的操作是非常复杂的,会占用很多CPU时间,对于移动设备来说频繁的垃圾回收会严重影响性能.下面的建议可以避免GC频繁操作 ...
- Java获取IP地址,IpUtils工具类,Java IP地址获取
================================ ©Copyright 蕃薯耀 2020-01-17 https://www.cnblogs.com/fanshuyao/ import ...
- day 9 深浅拷贝
浅copy 现有数据 data = { "name":"alex", "age":18, "scores":{ &quo ...
- ubuntu 1804 rsync 命令 服务端配置
1. rsync的主要作用 rsync命令是一个远程数据同步工具,可通过LAN/WAN快速同步多台主机间的文件.rsync使用所谓的"rsync算法"来使本地和远程两个主机之间的文 ...
- Wannafly Winter Camp 2020 Day 5F Inversion Pairs - 拉格朗日插值,dp
给定 \(n \leq 10^7\),求所有 \(n\) 的全排列的逆序对个数的 \(k \leq 100\) 次方和 Solution \(f[i][j]\) 表示 \(i\) 个元素,逆序对个数为 ...
- node-express处理表单的接口
写一个小接口,用postman测试接口是否可行