一.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.
4.仿函数:行为类函数,可作为算法的某种策略,从实现角度看,仿函数是一种重载了operator()的class或class template。
5.配接器:一种用来修饰容器或者仿函数或迭代器接口的东西。比如queue和stack,看着像容器,其实就是deque包了一层皮。
6.配置器:复制空间配置与管理,从实现角度看,配置器就是实现了动态空间配置、空间管理、空间释放的classtemplate。
二.STL底层数据结构实现
1.vector:数组,支持快速随机访问
2.map与multimap:红黑树, 实现O(lgn)的查找,插入和删除
3.unordered_map 与unordered_multimap: hash table
4.set & multiset:红黑树
5.unordered_set & unordered_multiset:hash table
6.priority_queue: 一般以vector为底层容器,heap为处理规则来管理底层容器实现
7.list:双向链表,特点是支持快速的增删
8.deque:一个中央控制器和多个缓冲区,支持首尾(中间不能)快速增删,支持随机访问
9.stack:底层用deque或者list实现,不用vector的原因是扩容耗时
10.queue 底层用deque或者list实现,不用vector的原因是扩容耗时
三、vector的底层机制
vector就是一个动态数组,里面有一个指针指向一片连续的内存空间,当空间不够装下数据时,会自动申请另一片更大的空间(一般是增加当前容量的50%或100%),然后把原来的数据拷贝过去,接着释放原来的那片空间;当释放或者删除里面的数据时,其存储空间不释放,仅仅是清空了里面的数据。
四、list的底层(存储)机制
以结点为单位存储数据,结点的地址在内存中不一定连续,每次插入或者删除一个元素,就配置或者释放一个元素空间。
五、list自带排序函数的排序原理
将前2个元素合并,再将后2个元素合并,然后合并这2个子序列成为4个元素序列的子序列,重复这一过程,得到8个,16个,,,,子序列,最后得到的就是排序后的序列。
六、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底层机制,查找复杂度,能不能边遍历边插入
红黑树,自平衡的二叉搜索树。自动排序效果不错。
查找复杂度:O(logN)
不可以,map不像vector,它在容器进行erase操作后不会返回后一个元素的迭代器,不能遍历地往后插删。
九、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以hashtable为底层,而map以红黑树为底层。hash_map查找速度比map快,而且查找速度基本和数据量大小无关,属于常数级别。而map的查找速度是logN级别。但不一定常数就比log小,而且hash_map还有hash function耗时。
十二、红黑树有什么性质?
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动态增加大小时,并不是在原空间后增加新的空间,而是以原大小的两倍在另外配置一片较大的新空间,然后将内容拷贝过来,并释放原来的空间。由于操作改变了空间,所以迭代器失效。
十五、vector、list、map、deque用erase(it)后,迭代器的变化。
vector和deque是序列式容器,其内存分别是连续空间和分段连续空间,删除迭代器it后,其后面的迭代器都失效了,此时it及其后面的迭代器会自动加1,使it指向被删除元素的下一个元素。
list删除迭代器it时,其后面的迭代器都不会失效,将前面和后面连接起来即可。
map也是只能使当前删除的迭代器失效,其后面的迭代器依然有效。
十六、hashtable和hashmap的区别
1.hashtable是Dictionary的子类,而hashmap是Map接口的一个实现类
2.hashtable中的方法是同步的,而hashmap的方法不同步
十七、auto_ptr可以做vector的元素吗?为什么?
不能。因为STL的标准容器规定它所容纳的元素必须是可以拷贝构造和可被转移赋值的。而auto_ptr不能,可以用shared_ptr智能指针代替。
十八、 快排算法的枢轴位置是怎么选择的?
三点中值法,取整个序列的头、尾、中央三个位置的元素,以其中值作为枢轴
十九、 简单说一下next_permutation和partition的实现?
-
next_permutation(下一个排列)
首先,从最尾端开始往前寻找两个相邻元素,另第一个元素为i,第二个元素为ii,且满足i<ii。找到这样一组相邻元素后,再从尾端开始往前检验,找出第一个大于i的元素j,将i,j元素对调,再将ii之后的所有元素颠倒排列。此即所求“下一个”排列组合。 -
partition
令头端迭代器first向尾部移动,尾部迭代器last向头部移动。当first所指的值大于或等于枢轴时就停下来,当last所指的值小于或等于枢轴时也停下来,然后检验两个迭代器是否交错。如果first仍然在last左边,就将连着元素互换,然后各自调整一个位置(向中央逼近),再继续进行相同的行为。如果发现两个迭代器交错了,表示整个序列已经调整完毕。
二十、不允许有遍历行为的容器有哪些?
1.queue ,除了头部外,没有其他方法存取deque的其他元素。
2.stack(底层以deque实现),除了最顶端外,没有任何方法可以存取stack的其他元素。
3.heap,所有元素都必须遵循特别的排序规则,不提供遍历功能。
总结:https://blog.csdn.net/tianya_team/article/details/50753759