zoukankan      html  css  js  c++  java
  • 海量数据处理方法总结

    最近这不准备面试么。看了些关于海量数据处理的相关面试题。

    网上比较有名的就是csdn的july大哥的秒杀99%海量数据那篇文章。的确是大大的干货。

    但是,个人感觉排版条理似乎不是那么清晰。故在看完july的全文后,我自己在此做个总结吧。

    这里,我们不谈例题,只谈思想和使用原则,下文以问答的方式进行总结。

    方法1:分而治之/hash映射 + hash_map统计 + 快速/堆/归并排序

    Q:方法1适用于哪些数据?

    A:一句话,适用于ip,字符串,query,日志项等非整型数值类型的数据。

    Q: hash本质是什么?

    A:所谓hash映射,指的是通过一种映射散列的方式让数据均匀分布在对应的内存位置(如大数据通过取余的方式映射成小数存放在内存中,或大文件映射成多个小文件)。

    正是因为如此,才需要hash映射,将相同的ip映射到同一个小文件中来,而且相同的IP在hash后,只可能落在同一个文件中,不可能被分散。

    hash的意义,一在于直接内存访问(这一点很多书就介绍过了),用映射后的数字作为下标直接访问内存。

    二点就是大文件映射成小文件,此时更强调“映射”的意义,在于大化小,而非内存。

    Q:如何具体将大文件映射为小文件?

    A: 一般情况是hash(data)%NUM。NUM即为你需要的小文件数。NUM的取值取决于划分后的小文件是否用内存装载得下。

    Q: hash_set和hash_map如何选择?

    A: hash_set主要用于判重,强调是否重复,hash_map主要用于统计次数,强调重复次数。其数据结构的特性决定了他们应该这样使用。

    Q: 归并排序和堆排序,两者不一样好么

    A: 注意到,这两个算法虽说不一样,但同样用在最后合并结果环节。而且比较多出现在topK问题中。

    如果需要用堆来计算topK。可以初始化一个堆,然后对每个小文件的topK数据依次扫描一遍,从而更新同样的一个“堆”。时间复杂度O(NlogK)

    如果需要用归并排序,则是把结果汇总,例如“取出出现频率最大的100个词(可以用含100个结点的最小堆)后,再把100个词及相应的频率存入文件,这样又得到了5000个文件。最后就是把这5000个文件进行归并(类似于归并排序)的过程了。”,最后得到归并的结果实则包含了top500000,然后取前100。多路归并时间复杂度为NMlogN。

    所以,前者适合topK。后者更适用于排序。

    Q: 有什么要补充的?

    A: 对于字符串而言,个人以为trie树更合适,不要上来就套用hash。

    另外,有一个题目,大意是一个数组每次插入一个数,要求实时寻找中位数,

    此时,可设置一个大根堆保存前N/2大的数据,一个小根堆保存前N/2小的数据。通过不断的平衡和选取两个堆的堆顶元素,实时计算中位数。

    方法二:(双层)桶划分

    Q: 适用数据?

    A: 很明显了,整形数值类数据,直白点说,数字。

    Q: 本质是什么?

    A: 其实还是分治的思想。把一大堆数据扔到一系列的桶中。扔进桶的规则不一而同。在海量数据中,每个桶可以理解为一个区间[x,y]。桶中的数据集较小,可直接处理。

    对于单一的桶,可排序,可统计,有选择的操作将会降低整体算法的时间复杂度。

    如果桶容量为1,而且用1bit来表示,就是bitmap了。

    Q: 和桶排序,基数排序的区别?

    A: 这里谈的是桶划分,还没牵涉到排序。

    基数排序也用到了桶划分的思想,但是是以个位,十位,百位。。。这样划分的。而且10个桶就可以搞定。但是得跑几轮。

    桶排序也是按照桶划分的思想,把数据按照规则扔到桶内,对桶内的数据进行排序,然后按桶序输出。

    可以看到,桶划分的规则也可以看做一种特殊的hash,一种划分范围的hash。不是么?

    方法三:bloom filter/bitmap

    Q: 使用场合?

    A: 这两种方法主要用于判重,查找,对于bitmap还可以用来排序。

    Q: 本质是什么?

    A: 对于bloom filter,本质就是位数组+k个hash函数。bitmap就是对应的位置1。

    其实,bitmap和bloom filter本质上还是hash。只不过是一种新的映射方案罢了。

    Q: 需要注意的地方?

    A:

    bloom filter需要注意,如何根据输入元素个数n,确定位数组m的大小及hash函数个数

    这里有个公式,当hash函数个数k=(ln2)*(m/n)时错误率最小,在错误率不大于E的情况下,m至少要等于n*lg(1/E)才能表示任意n个元素的集合,

    但m还应该更大些,因为还要保证bit数组里至少一半为0,则m>=nlg(1/E)*lge 大概就是nlg(1/E)1.44倍(lg表示以2为底的对数)。

    方法四:Trie树/数据库/倒排索引/外排序

    没啥好说的。参见相关方法细节即可。需要注意的是有可能与上述方法结合起来用。

  • 相关阅读:
    H.Playing games
    P4721 【模板】分治 FFT
    hdu5730 分治fft
    hdu6394Tree lct
    bzoj2763: [JLOI2011]飞行路线 最短路
    bzoj2154: Crash的数字表格 莫比乌斯反演
    bzoj3211: 花神游历各国 线段树
    溢流
    css控制继承
    “<textarea>”内的文字对齐
  • 原文地址:https://www.cnblogs.com/ShaneZhang/p/3726038.html
Copyright © 2011-2022 走看看