某日二师兄参加XXX科技公司的C++工程师开发岗位第27面:

面试官:用过std::set/std::map吗?

二师兄:用过。

面试官:能介绍一下二者吗?

二师兄:std::set是一个有序的集合,其中的元素是唯一的,即每个元素只能出现一次。一般用于去重和自动排序。

二师兄:std::map同样是有序组合,只不过它不止有key,每个key还对用一个value。其中key是唯一,不可重复,但是value却没有限制。key/value也被称为键值对。

面试官:知道他们底层使用什么数据结构存储数据的吗?

二师兄:两者都是使用红黑树作为底层的数据结构。红黑树是一种自动平衡的二叉树,它确保插入、删除和查找操作的时间复杂度都是O(log n)

面试官:set/map对于key的类型有什么要求吗?

二师兄:因为set/map被称为有序容器,所以对插入进去的key有排序的要求。一般需要为类型实现<比较方法,以下代码无法通过编译:

#include <iostream>
#include <set>
struct Foo
{
Foo(int v):val(v){}
int val;
};
int main(int argc, char const *argv[])
{
std::set<Foo> iset;
iset.insert(Foo(1024));
iset.insert(Foo(42));
for(auto it = iset.begin(); it != iset.end(); ++it)
{
std::cout << it->val << std::endl;
}
return 0;
}

二师兄:此时需要为Foo类型实现bool operator<(const T&, const T&)函数,才能通过编译:

bool operator<(const Foo& lhs,const Foo& rhs) {return lhs.val < rhs.val;}

面试官:按照你的方法,可以实现从小到大的排序。如何实现从大到小的排序?

二师兄:set/map类模板的第二个模板参数可以传入比较类型,默认比较类型是std::less<_Key>,我们可以传入std::greater<T>,此时需要实现bool operator>(const T&, const T&)函数。

二师兄:还有一种方法是手写一个仿函数,重载bool operator()(const T, const T) const函数用于比较两者的大小:

struct Comp
{
bool operator()(const Foo& lhs, const Foo& rhs) const
{
return lhs.val > rhs.val;
}
};
std::set<Foo,Comp> iset;

面试官:可以修改map中的key吗?

二师兄:不可以。因为map中的keyconst的。强制修改(取地址,const_cast转非const指针,解引用赋值)会造未知的错误。

面试官:当map中不存在某个key时,对map使用map[key]操作会有什么后果?

二师兄:会在map中增加一个键值对,键名为key,值是传入的value类型的默认值。

面试官:如果不希望删除重复的key,有什么办法?

二师兄:STL中提供了std::multisetstd::multimap两个容器,可以存入key相同的多个元素。

面试官:在std::multimap中如何通过key查找value

二师兄:multimap提供了equal_range方法,此方法返回一个pair,分别对应2个迭代器。通过循环迭代器来获取key对应的所有value

#include <iostream>
#include <map>
int main() {
std::multimap<int, std::string> mmap;
mmap.insert(std::make_pair(1, "1"));
mmap.insert(std::make_pair(2, "2"));
mmap.insert(std::make_pair(3, "3"));
mmap.insert(std::make_pair(1, "1"));
auto range = mmap.equal_range(1);
for (auto it = range.first; it != range.second; ++it) {
std::cout << it->second << std::endl;
}
return 0;
}

面试官:最后一个问题,你觉得单纯的查询而言,是vector快还是map快?

二师兄:当然是map快,因为vector的查询的时间复杂度是O(n),而map是O(logn)

面试官:好的,今天面试结束了,回去等通知吧。

让我们看看最后一个问题:

单纯的查询而言,是vector快还是map快?

这里二师兄的是标准答案,实际上当数据量特别大的时候,的确map是更好的选择。

但当数据量没那么大的时候(少于1000条记录),vector要比map查询速度快。原因我们在之前的面试文章中讲过,vector内存连续,缓存更友好。map底层是红黑树,内存并不连续。

当数据量小的时候,算法的优势没有抵消缓存的劣势,所以vector在数据量小的时候更胜一筹。

“纸上得来终觉浅,绝知此事要躬行”。小伙伴们,一起努力吧!

关注我,带你21天“精通”C++!(狗头)

C++面试八股文:用过std::set/std::map吗?的更多相关文章

  1. std::unique_lock<std::mutex> or std::lock_guard<std::mutex> C++11 区别

    http://stackoverflow.com/questions/20516773/stdunique-lockstdmutex-or-stdlock-guardstdmutex The diff ...

  2. hdu 1053 (huffman coding, greedy algorithm, std::partition, std::priority_queue ) 分类: hdoj 2015-06-18 19:11 22人阅读 评论(0) 收藏

    huffman coding, greedy algorithm. std::priority_queue, std::partition, when i use the three commente ...

  3. 单独删除std::vector <std::vector<string> > 的所有元素

    下面为测试代码: 1.创建 std::vector< std::vector<string> > vc2; 2.初始化 std::vector<string> vc ...

  4. C++11 std::bind std::function 高级使用方法

    从最基础的了解,std::bind和std::function /* * File: main.cpp * Author: Vicky.H * Email: eclipser@163.com */ # ...

  5. LeetCode 26 Remove Duplicates from Sorted Array [Array/std::distance/std::unique] <c++>

    LeetCode 26 Remove Duplicates from Sorted Array [Array/std::distance/std::unique] <c++> 给出排序好的 ...

  6. 没有与这些操作数匹配的 "<<" 运算符 操作数类型为: std::ostream << std::string

    错误显示:没有与这些操作数匹配的 "<<" 运算符       操作数类型为:  std::ostream << std::string 错误改正:要在头文 ...

  7. matlab转c++代码实现(主要包含C++ std::vector,std::pair学习,包含数组与常数相乘,数组相加减,将数组拉成一维向量,图片的读入等内容)

    MATLAB部分: xmap = repmat( linspace( -regionW/2, regionW/2, regionW), regionH, 1 );%linspace [x1,x2,N] ...

  8. std::lock_guard/std::unique_lock

    C++多线程编程中通常会对共享的数据进行写保护,以防止多线程在对共享数据成员进行读写时造成资源争抢导致程序出现未定义的行为.通常的做法是在修改共享数据成员的时候进行加锁--mutex.在使用锁的时候通 ...

  9. std::binary_serach, std::upper_bound以及std::lower_bound

    c++二分查找的用法 主要是 std::binary_serach,  std::upper_bound以及std::lower_bound 的用法,示例如下: std::vector<int& ...

  10. C++11 并发指南四(<future> 详解三 std::future & std::shared_future)

    上一讲<C++11 并发指南四(<future> 详解二 std::packaged_task 介绍)>主要介绍了 <future> 头文件中的 std::pack ...

随机推荐

  1. 有关idea的使用部分

    出现相关异常,提示类似粗在idea找不到相关的包加载失败. 执行mvn命令 mvn -U idea:idea 含义更新重新加载idea工程的相关jar

  2. java 回行矩阵的打印

    n=3 n=4 1   2   3 1    2 3   4 8   9   4 12 13      14     5 7   6   5 11 16      15     6 10 9      ...

  3. 脚本:Oracle巡检html版

    做一个日常巡检oracle数据库的脚本,生成一个html版本,简介方便查看 check_db.sql 1.数据库情况 2.数据文件及表空间情况 3.数据库性能问题 4.加入邮件,定期发送到邮箱 发件语 ...

  4. Cron表达式介绍与示例

      1. 概念介绍 Cron表达式是一个具有时间含义的字符串,字符串以5~6个空格隔开,分为6~7个域,格式为X X X X X X X.其中X是一个域的占位符.最后一个代表年份的域非必须,可省略.单 ...

  5. Appweb交叉编译

    Appweb交叉编译 编译环境:ubuntu-12.04 x64 开发平台:Hi3535 arm版 编译版本:appweb-6.1.1.zip 下载地址=> Appweb web site: h ...

  6. HTAP for MySQL 在腾讯云数据库的演进

    摘要:MySQL在充分利用多核计算资源方面比较欠缺,无法同时满足在线业务和分析型业务的客户需求,而单独部署一套专用的分析型数据库意味着额外的成本和复杂的数据链路.本次主题将介绍腾讯云数据库为满足此类场 ...

  7. bean的作用域和@scope注解

    bean的作用域由@scope注解来修改,该注解有五个不同的取值,分别是:singleton.prototype.request.session.global-session. singleton,在 ...

  8. 2020-01-25:redis中,哨兵如何选举?

    福哥答案2020-01-25: [答案1:](https://bbs.csdn.net/topics/398982967)redis-sentinel故障转移的流程:1.当多个sentinel发现并确 ...

  9. 2022-02-15:扫地机器人。 房间(用格栅表示)中有一个扫地机器人。 格栅中的每一个格子有空和障碍物两种可能。 扫地机器人提供4个API,可以向前进,向左转或者向右转。每次转弯90度。 当扫地机

    2022-02-15:扫地机器人. 房间(用格栅表示)中有一个扫地机器人. 格栅中的每一个格子有空和障碍物两种可能. 扫地机器人提供4个API,可以向前进,向左转或者向右转.每次转弯90度. 当扫地机 ...

  10. sipp重放rtp数据测试FreeSWITCH

    环境:CentOS 7.6_x64 FreeSWITCH版本 :1.10.9 sipp版本:3.6.1 一.背景描述 sipp是一款VoIP测试工具,日常开发过程中会使用到该软件,但其自身携带的pca ...