哈希函数又叫散列函数,哈希函数的输入域可以是非常大的范围,比如任意字符串,但是输出域是固定范围,假设为s。
哈希函数的性质:
难点:通讯,时间与空间的估算。
请对10亿个IPV4的地址进行排序,每个ip只会出现一次。
分析:一个ip地址相当于一个四字节的整数。申请一个大小为 2 32 2^{32} 232的bit类型的数组初始化为 0 0 0,每当遇到一个IPV4就将数组对应位置变为 1 1 1。这样就记录了所有出现过的IPV4,然后再将数组转化为IPV4,就是排序后的IPV4。
给定10亿个整数,每个整数代表一个人的年龄,请对这10亿人的年龄进行排序。
分析:申请一个大小为200的数组,每出现一个整数,数组对应位置+1,就完成排序了。
有一个包含20亿个全是32位整数的大文件,在其中找到出现次数最多的数。但是内存限制只有2G。
分析:
通常使用哈希表对每个数进行词频统计,如果key与value都是32位的整数,则2亿条记录就会占用1.6G内存。一次性统计会产生内存超出。
方法:使用哈希函数将大文件中的数据分流,假设分为16个小文件,根据哈希函数的性质,同一种数不能被分流道不同的文件中。因此可以在同一个文件中统计出这种数出现的次数,并且哈希函数对每个小文件的分配也是非常均匀的。选取16个小文件中出现的最多的数再进行比较,可以得到最终结果。
32位无符号整数的范围是0~4294967295。现在有一个正好包含40亿个无符号整数的文件,所以在整个范围中必然有没出现过的数。可以使用最多10M的内存,只用找到一个没出现过的数即可,该如何找?
分析:如果用哈希表或者bitMap(500M)都会出现超内存。将 0 0 0~ 2 32 1 2^{32}-1 2321平均分为64个区间,必然有一个区间数量小于 2 32 / 64 2^{32}/64 232/64,找到任意一个这样的区间,然后再该区间内建立bitMap,只需要8M内存。
某搜索公司一天的用户搜索词汇是海量的,假设有百亿的数据量,请设计一种求出每天最热100词的可行办法。
分析:利用哈希函数进行分流,然后对每个小文件利用哈希表进行词频计数,然后利用小根堆进行前100的排序,然后将每个小文件合并排序,最终选出最热100词。
工程师常使用服务器集群来设计和实现数据缓存,以下是常见的策略。1. 无论是添加、查询还是删除数据,都先将数据的id通过哈希函数映射为一个哈希值,记为key。2. 如果目前机器有N台,则计算key%N的值,这个值就是该机器所属的数据编号,无论是添加、查询还是删除都是在这台机器上进行。请分析这种缓存策略可能带来的问题,并提出改进方案。
分析:如果增加或删除机器,数据迁移的代价很大。需要根据新机器数,重新计算一遍哈希值,然后再将数据重新划分到新的机器中。
改进:一致性哈希算法
将计算后得到的哈希值想象为一个闭合的环形,一个数据根据id通过哈希函数对应到环中的位置。然后想象有三台机器,根据机器id计算出哈希值,放到环中的对应位置,然后将数据放到顺时针最近的机器进行处理。