C++进阶:封装unordered_map和unordered_set以及海量数据面试题

本文介绍了C++中的unordered_map和unordered_set的原理与实现,包括它们在海量数据处理中的应用,如哈希切割解决大文件IP统计问题和位图在快速查找和排序中的作用。同时,文章探讨了布隆过滤器的插入、删除、优缺点及其在内存受限情况下的交集计算策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

unordered系列关联式容器
  • unordered_map
    1、概念
    unordered_map是存储<key,value>键值对的关联式容器,允许通过key快速的索引到与其对应的value。
    在unordered_map中,键值通常用于惟一地标识元素,而映射值是一个对象,其内容与此键关联。键和映射值的类型可能不同。在内部,unordered_map没有对<key, value>按照任何特定的顺序排序, 为了能在常数范围内找到key所对应的value,unordered_map将相同哈希值的键值对放在相同的桶中。unordered_map容器通过key访问单个元素要比map快,但它通常在遍历元素子集的范围迭代方面效率较低。unordered_map实现了直接访问操作符(operator[]),它允许使用key作为参数直接访问value。 它的迭代器至少是前向迭代器。
    2、利用哈希桶来实现unordered_map
    我们在上一篇关于开散列的介绍中,已经实现了哈希桶的基本功能,但是所实现的并不能够封装unordered_map,因为unordered_map的存储结构是<key,value>的键值对,而我们所实现的只是存放普通的元素,而且unordered_map的一些接口(例如插入、删除)也与哈希桶的不同,因此,在这里我们将哈希桶的功能再完善一些
    我们通过仿函数的方式按照key值获取到value,也就是增加一个模板类型KeyOfValue
    让它实现通过key来获取value
  • unordered_set
    unordered_set的实现只需要将unordered_map的实现改造一下即可(注意unordered_set没有通过下标来获取的运算符重载)
    源代码(github):
    https://github.com/wangbiy/C-3/commit/07794688cb909369130761528ed1d4fcff06ed14
海量数据面试题
  • 1、哈希切割
    给一个超过100G大小的log file, log中存着IP地址, 设计算法找到出现次数最多的IP地址?
    如果我们按照传统的方式进行两个循环来统计,由于文件比较大,十分耗费时间,如果采用归并排序的方法也没有办法很好的解决这个问题,这时就要用到哈希切割
    (1)哈希切割就是将一个大文件,利用哈希原理将其分割成为若干个小文件(根据用户的限制估算被分割成文件的份数),然后获取每条IP地址,将IP地址(字符串)转换为整数(网络部分的库函数),然后将每个IP地址映射到相应文件中:IPINT%分割份数,此时相同的数据被分到同一个小文件中;然后统计IP地址的次数:即构建键值对unordered_map<IPINT,次数>,使用unordered_map来统计
    (2)找到出现次数最多的IP地址
    使用multimap<次数,IP地址>(底层是红黑树,已经根据次数排序好了)来查找
    这样我们一共只遍历了一次,提高了性能,I/O次数降低
    与上题条件相同,如何找到top K的IP?如何直接用Linux系统命令实现?
    要建一个小堆—priority_queue(放的元素的类型是pair<次数,IP地址>),通过比较来找前k个次数最多的IP地址,即建立一个K个元素的小堆
    用Linux命令实现:sort log_file | uniq -c | sort -nr k1,1 | head -10;
  • 2、哈希应用:位图
    例如面试题:给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中
    首先40亿整形数据大概估算是15G的大小,根本无法直接一次加载到内存中(一般计算机的内存是4G或者8G,还给系统内存分了2G的空间),所以如果采用遍历的方式来查找,需要分割这个数据,效率太低;
    还有一种方法是进行排序,然后进行二分查找,但是这种方式还要加载数据,效率太低;
    因此我们需要位图来解决这种问题
    也就是数据是否在给定的整形数据中,结果是在或者不在,刚好是两种状态,那么可以使用一个二进制比特位来代表数据是否存在的信息,如果二进制比特位为1,代表存在,为0代表不存在。
    先给一个例子:
    如图:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值