map 、set、multiset、multimap 底层原理及其相关面试题

(1)map 、set、multiset、multimap的底层原理

map 、set、multiset、multimap的底层实现都是红黑树,epoll模型的底层数据结构也是红黑树,linux系统中CFS进程调度算法,也用到红黑树。

在这里插入图片描述

红黑树的特性:

  1. 每个结点或是红色或是黑色;

  2. 根结点是黑色;

  3. 每个叶结点是黑的;

  4. 如果一个结点是红的,则它的两个儿子均是黑色;

  5. 每个结点到其子孙结点的所有路径上包含相同数目的黑色结点。

红黑树详解具体看这篇:别再问我什么是红黑树了

对于STL里的map容器,count方法与find方法,都可以用来判断一个key是否出现,mp.count(key) > 0统计的是key出现的次数,因此只能为0/1,而mp.find(key) != mp.end()则表示key存在。

(2)map 、set、multiset、multimap的特点

set和multiset会根据特定的排序准则自动将元素排序,set中元素不允许重复,multiset可以重复。

map和multimap将key和value组成的pair作为元素,根据key的排序准则自动将元素排序(因为红黑树也是二叉搜索树,所以map默认是按key排序的),map中元素的key不允许重复,multimap可以重复。

map和set的增删改查速度为都是logn,是比较高效的。

(3)为何map和set的插入删除效率比其他序列容器高,而且每次insert之后,以前保存的iterator不会失效?

因为存储的是结点,不需要内存拷贝和内存移动。

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

(4)为何map和set不能像vector一样有个reserve函数来预分配数据?

因为在map和set内部存储的已经不是元素本身了,而是包含元素的结点。也就是说map内部使用的Alloc并不是map<Key, Data, Compare, Alloc>声明的时候从参数中传入的Alloc。

(5)map 、set、multiset、multimap的常用函数
it map.begin()          返回指向容器起始位置的迭代器(iterator) 
it map.end()             返回指向容器末尾位置的迭代器 
bool map.empty()         若容器为空,则返回true,否则false
it map.find(k)           寻找键值为k的元素,并用返回其地址
int map.size()           返回map中已存在元素的数量
map.insert({int,string}) 插入元素
for (itor = map.begin(); itor != map.end();)
{
    if (itor->second == "target")
        map.erase(itor++) ; // erase之后,令当前迭代器指向其后继。
    else
        ++itor;
}

发表评论

后才能评论

评论(2)